<%@ WebHandler Language="C#" Class="Maze2D" %> using System; using System.Web; using System.IO; using System.Text; using System.Text.RegularExpressions; using Amundsen.Utilities; using DFSAlgorithmMaze; public class Maze2D : IHttpHandler { HttpContext ctx = null; WebUtility wu = new WebUtility(); string[] ctypes = new string[] { "application/x-www-form-urlencoded" }; string[] accepted = new string[] { "text/html","application/xml","text/plain","text/xml","application/vnd.amundsen.maze+xml"}; bool debug = true; string mazeFolder = "2d"; string mazeFormat = "http://amundsen.com/examples/mazes/2d/{0}/"; string roomFormat = "http://amundsen.com/examples/mazes/2d/{0}/{1}:{2}"; // xml representation string collStartXml = "\n\n"; string collLineXml = "\n"; string collStopXml = "\n"; string itemLineXml = "\n\n\n\n\n{1}\n\n\n"; string roomStartXml = "\n\n\n\n"; string roomLineXml = "\n"; string roomStopXml = "\n"; string exitLineXml = "\n\n\n\n\n"; // xhtml representation string collStartHtml = "\n\n\n\nmaze 2d\n\n\n\n
\n\n
\n\n"; string itemLineHtml = "\n\n\n\nmaze 2d\n\n\n\n
\n
\nstart\n
\n
\n
{1}
\n
\n
\n\n"; string roomStartHtml = "\n\n\n\nmaze 2d\n\n\n\n
\n\n
\n
\n

You are facing:

{4}

\n\"0\"/\"1\"/\"2\"/\n
\n"; string roomStopHtml = "\n"; string exitLineHtml = "\n\n\n\nmaze 2d\n\n\n\n
\nstart\n
\n\n"; public void ProcessRequest(HttpContext context) { ctx = context; string method = ctx.Request.HttpMethod.ToLower(); try { switch (method) { case "get": Get(); break; case "head": Get(true); break; case "post": Post(); break; case "options": Options(); break; default: Options(405); break; } } catch (HttpException hex) { ctx.Response.ContentType = "text/plain"; ctx.Response.StatusCode = hex.GetHttpCode(); ctx.Response.StatusDescription = hex.Message; ctx.Response.Write(string.Format("{0} - {1}", hex.GetHttpCode(), hex.Message)); } catch (Exception ex) { ctx.Response.ContentType = "text/plain"; ctx.Response.StatusCode = 500; ctx.Response.StatusDescription = ex.Message; ctx.Response.Write(string.Format("{0} - {1}", 500, (debug==true?ex.StackTrace:ex.Message))); } } public bool IsReusable { get { return false; } } private void Options() { Options(200); } private void Options(int response) { string content = string.Empty; string accept = string.Empty; string msg = string.Empty; string methods = string.Empty; for(int i = 0; i; rel=\"maze\"", string.Format(mazeFormat,coll[i].Name.Replace(".maze", "")), coll[i].Name ); } data += collStop; // transform into proper media type ctx.Response.AddHeader("Link",linkHdr); // send results to caller return data; } private string GetMaze(string id, string accept) { string data = string.Empty; string rtn = string.Empty; string linkHdr = string.Empty; string itemLine = (accept=="text/html"?itemLineHtml:itemLineXml); // get item from disk data = ReadFile(id); // transform into proper media type rtn = string.Format(itemLine,string.Format(roomFormat,id,"0","north"),data); linkHdr = string.Format("<{0}>; rel=\"start\"",string.Format(roomFormat,id,"0","north")); ctx.Response.AddHeader("Link",linkHdr); // send results to caller return rtn; } private string GetMove(string id, string mv, string accept) { string data, rtn; string[] cells; string[] rm; int m = 0; string[] mx = new string[2]; if(mv.IndexOf(":")!=-1) { mx[0]=mv.Split(':')[0]; mx[1]=mv.Split(':')[1]; } else { mx[0]=mv; mx[1]=string.Empty; } if (mx[0] == "999") { rtn = ShowExit(id,accept,mx[1]); } else { data = ReadFile(id); cells = data.Split('\n'); m = Int32.Parse(mx[0]); rtn = cells[m]; rm = cells[m].Split(','); switch (accept) { default: rtn = TransformRoom(id, cells[m], cells.Length - 1, accept,mx[1]); break; } } return rtn; } private string ShowExit(string mz,string accept, string dx) { string rtn = string.Empty; string exitLine = (accept=="text/html"?exitLineHtml:exitLineXml); ctx.Response.AddHeader("Link",string.Format("<{0}>; rel=\"start\"", string.Format(roomFormat,mz, 0,"north"))); rtn = string.Format(exitLine, string.Format(roomFormat,mz, 0,"north")); return rtn; } private string TransformRoom(string mz, string rm,int total, string accept, string dx) { string linkHdr = string.Empty; string rtn = string.Empty; string[] images = new string[]{"images/middle-nodoor.png","images/left-nodoor.png","images/middle-nodoor.png","images/right-nodoor.png"}; string id = string.Empty; string[] s; int x; string roomStart = (accept=="text/html"?roomStartHtml:roomStartXml); string roomLine = (accept=="text/html"?roomLineHtml:roomLineXml); string roomStop = (accept=="text/html"?roomStopHtml:roomStopXml); string roomImages = (accept=="text/html"?roomImagesHtml:string.Empty); rtn = string.Empty; id = rm.Split(':')[0]; s = rm.Split(':')[1].Split(','); x = Convert.ToInt32(Math.Sqrt((double)total)); linkHdr += string.Format("<{0}>; rel=\"current\"", string.Format(roomFormat,mz, id,dx)); rtn = string.Format(roomStart, string.Format(roomFormat, mz, id, dx), rm, total, x); if (Int32.Parse(id) == total-1) { SetDoor(ref images,"exit",0,"door"); linkHdr += string.Format(",<{0}>; rel=\"{1}\"", string.Format(roomFormat,mz,"999",dx), "exit"); rtn += string.Format(roomLine, string.Format(roomFormat,mz,"999",dx), "exit"); } else { for (int i = 0; i < s.Length; i++) { if (i == 0) { if(s[i] == "0") { SetDoor(ref images,dx,0,"door"); linkHdr += string.Format(",<{0}>; rel=\"{1}\"", string.Format(roomFormat,mz,Int32.Parse(id) - 1,"north"), "north"); rtn += string.Format(roomLine, string.Format(roomFormat,mz,Int32.Parse(id) - 1,"north"), "north"); } else { SetDoor(ref images,dx,0,"nodoor"); } } if (i == 1) { if(s[i] == "0") { SetDoor(ref images,dx,1,"door"); linkHdr += string.Format(",<{0}>; rel=\"{1}\"", string.Format(roomFormat,mz,Int32.Parse(id) + (x * -1),"west"), "west"); rtn += string.Format(roomLine, string.Format(roomFormat,mz,Int32.Parse(id) + (x * -1),"west"), "west"); } else { SetDoor(ref images,dx,1,"nodoor"); } } if (i == 2) { if(s[i] == "0") { SetDoor(ref images,dx,2,"door"); linkHdr += string.Format(",<{0}>; rel=\"{1}\"", string.Format(roomFormat,mz,Int32.Parse(id) + 1,"south"), "south"); rtn += string.Format(roomLine, string.Format(roomFormat,mz,Int32.Parse(id) + 1,"south"), "south"); } else { SetDoor(ref images,dx,2,"nodoor"); } } if (i == 3) { if(s[i] == "0") { SetDoor(ref images,dx,3,"door"); linkHdr += string.Format(",<{0}>; rel=\"{1}\"", string.Format(roomFormat,mz,Int32.Parse(id) + x,"east"), "east"); rtn += string.Format(roomLine, string.Format(roomFormat,mz,Int32.Parse(id) + x,"east"), "east"); } else { SetDoor(ref images,dx,3,"nodoor"); } } } } rtn += string.Format(roomImages, images[0],images[1],images[2],images[3],dx); rtn += roomStop; ctx.Response.AddHeader("Link",linkHdr); return rtn; } private void SetDoor(ref string[] images,string facing, int i, string door) { if(facing=="exit") { images[0] = "images/left-nodoor.png"; images[1] = "images/middle-door.png"; images[2] = "images/right-nodoor.png"; } if(facing=="north" && i==0) { images[1] = "images/middle-"+door+".png"; } if(facing=="north" && i==1) { images[0] = "images/left-"+door+".png"; } if(facing=="north" && i==2) { images[3] = ""; } if(facing=="north" && i==3) { images[2] = "images/right-"+door+".png"; } if(facing=="west" && i==0) { images[2] = "images/right-"+door+".png"; } if(facing=="west" && i==1) { images[1] = "images/middle-"+door+".png"; } if(facing=="west" && i==2) { images[0] = "images/left-"+door+".png"; } if(facing=="north" && i==3) { images[3] = ""; } if(facing=="south" && i==0) { images[3] = ""; } if(facing=="south" && i==1) { images[2] = "images/right-"+door+".png"; } if(facing=="south" && i==2) { images[1] = "images/middle-"+door+".png"; } if(facing=="south" && i==3) { images[0] = "images/left-"+door+".png"; } if(facing=="east" && i==0) { images[0] = "images/left-"+door+".png"; } if(facing=="east" && i==1) { images[3] = ""; } if(facing=="east" && i==2) { images[2] = "images/right-"+door+".png"; } if(facing=="east" && i==3) { images[1] = "images/middle-"+door+".png"; } //return rtn; } private void Post() { string ctype = string.Empty; string defaultSize = "10"; string size = string.Empty; string slug = string.Empty; int sz = 0; // confirm media type ctype = ctx.Request.Headers["content-type"]; ctype = MimeParse.BestMatch(ctypes, ctype); if (ctype == string.Empty) { Options(415); return; } // get slug, if it exists slug = (ctx.Request.Headers["slug"]!=null?ctx.Request.Headers["slug"]:System.Guid.NewGuid().ToString()); if(IsValidName(slug)==false) { throw new HttpException(400,"Invalid Slug Name. Only letters, numbers, and the dash allowed."); } // get size, if it exists size = (ctx.Request["size"]!=null?ctx.Request["size"]:defaultSize); if (size == string.Empty) { throw new HttpException(400, "Missing size argument"); } try { sz = Int32.Parse(size); if (sz < 5 || sz > 50) { throw new HttpException(400, "Invalid size argument. Must be an integer between 5 and 50"); } } catch (Exception ex) { throw new HttpException(400, "Invalid size argument. Must be an integer between 5 and 50"); } // generate & store maze Maze m = GenMaze(sz); string id = SaveMaze(m,slug); // return 201 + location ctx.Response.ContentType = "text/plain"; ctx.Response.StatusCode = 201; ctx.Response.StatusDescription = "Created"; ctx.Response.RedirectLocation = string.Format(mazeFormat, id); ctx.Response.Write(string.Format(mazeFormat, id)); } private Maze GenMaze(int sz) { Maze.kDimension = sz; Maze m = new Maze(); m.Initialize(); m.Generate(); return m; } private string SaveMaze(Maze m, string slug) { string id = slug; string path = string.Empty; Cell[,] coll = m.Cells; int ix = coll.GetLength(0); int jx = coll.GetLength(1); System.Text.StringBuilder sb = new StringBuilder(); int z = 0; for (int i = 0; i < ix; i++) { for (int j = 0; j < jx; j++) { sb.AppendFormat("{0}:", z++, i, j); for (int k = 0; k < coll[i, j].Walls.Length; k++) { sb.Append(coll[i, j].Walls[k]); if (k < 3) { sb.Append(","); } else { sb.Append("\n"); } } } } // validate path path = ctx.Server.MapPath(string.Format("{0}/{1}.maze", mazeFolder, id)); if(File.Exists(path)==true) { id = System.Guid.NewGuid().ToString(); path = ctx.Server.MapPath(string.Format("{0}/{1}.maze", mazeFolder, id)); } // save to disk using (StreamWriter sw = new StreamWriter(path.ToLower())) { sw.Write(sb.ToString()); sw.Close(); } return id; } private bool IsValidName(string slug) { bool match = false; try { Regex regexObj = new Regex(@"\A([a-z0-9\-]*)\Z"); match = regexObj.IsMatch(slug); } catch (ArgumentException ex) { throw new HttpException(500,"|"+slug+"|"+ex.Message); } return match; } private string ReadFile(string id) { string path = string.Empty; string data = string.Empty; path = ctx.Server.MapPath(string.Format("{0}/{1}.maze",mazeFolder,id)); using(StreamReader sr = new StreamReader(path)) { data = sr.ReadToEnd(); sr.Close(); } return data; } }