예제 #1
0
        public void A2_MoveUser_Test()
        {
            HTMLRenderer r = new HTMLRenderer();
            GoGame       g = new GoGame(r);

            g.Init(5, 5);

            Assert.AreEqual(0, g.User.X);

            g.MoveUser("RIGHT");

            Assert.AreEqual(1, g.User.X);
        }
예제 #2
0
        static void Main(string[] args)
        {
            // мы тут тестируем наш рендерер - он рендерит не в HTML а в консоль, тоесть там просто нет <br />
            ConsoleRenderer r = new ConsoleRenderer();

            GoGame g = new GoGame(r);

            g.Init(5, 5);

            g.MoveUser(GoGame.D_RIGHT);
            g.MoveUser(GoGame.D_DOWN);

            String temp = g.RenderField();

            Console.WriteLine(temp);
        }
예제 #3
0
        public void A1_Dimensions_Test()
        {
            HTMLRenderer r = new HTMLRenderer();
            GoGame       g = new GoGame(r);

            g.Init(5, 5);

            Assert.AreEqual(5, g.DimX);
            Assert.AreEqual(5, g.DimY);

            g = new GoGame(r);

            g.Init(10, 5);

            Assert.AreEqual(10, g.DimX);
            Assert.AreEqual(5, g.DimY);
        }
예제 #4
0
        static void Main(string[] args)
        {
            App.Add(x =>
            {
                return(new HTTPContext {
                    RawURL = ""
                });
            });

            App.Add(x =>
            {
                return(new HTTPContext {
                    RawURL = x.RawURL.TrimStart('/')
                });
            });

            App.Add(x =>
            {
                return(HTTPContext.CreateContext(x.RawURL));
            });

            HTMLRenderer r = new HTMLRenderer();

            game = new GoGame(r);

            HttpListener listener = new HttpListener();

            listener.Prefixes.Add("http://*:55555/");
            listener.Start();

            Console.WriteLine("listening");
            game.Init(10, 5);

            while (true)
            {
                HttpListenerContext context = listener.GetContext();
                HttpListenerRequest request = context.Request;

                String rawurl = request.RawUrl;

                App.Init(rawurl);

                String responsestring = "";

                App.Run();

                if (!rawurl.Contains('.'))
                {
                    HTTPContext ct = App.GetContext();

                    if (ct != null)
                    {
                        Assembly asm = Assembly.GetCallingAssembly();

                        List <TypeInfo> Controllers = asm.DefinedTypes.Where(x => x.BaseType == typeof(Controller)).ToList();

                        AssemblyName an = asm.GetName();

                        String ClassName = Controllers
                                           .Where(x => x.Name == ct.Controller)
                                           .SingleOrDefault()?
                                           .FullName;

                        ObjectHandle tclass = Activator.CreateInstance(an.Name, ClassName);

                        Type type = asm.GetType(ClassName);

                        object unwc = tclass.Unwrap();

                        ((Controller)unwc).Context = ct;

                        if (ct.Action != null)
                        {
                            responsestring = type.GetMethod(ct.Action).Invoke(unwc, null).ToString();
                        }
                    }
                }
                else
                {
                    game.MoveUser(App.GetContext().RawURL);
                    String GameField = game.RenderField();

                    String tfile = GetFileContent("Game");

                    tfile = tfile.Replace("<game />", GameField);

                    responsestring = tfile;
                }

                HttpListenerResponse response = context.Response;

                byte[] buffer = Encoding.UTF8.GetBytes(responsestring);
                response.ContentLength64 = buffer.Length;
                Stream output = response.OutputStream;
                output.Write(buffer, 0, buffer.Length);
                output.Close();

                Console.WriteLine($"String {responsestring} sent to client");
            }
        }
예제 #5
0
        static void Main(string[] args)
        {
            // создаём HTML версию рендерера
            HTMLRenderer r = new HTMLRenderer();

            // создаём объект игры и пробрасываем ему рендерер (внедрение через конструктор)
            game = new GoGame(r);

            // создаём слушатель HTTP запросов
            HttpListener listener = new HttpListener();

            // настраиваем его чтобы он слушал на определённом порту
            listener.Prefixes.Add("http://*:55555/");
            // стартуем его
            listener.Start();

            // на всякий случай выводим в консоль чтобы мы знали что сервер слушает
            Console.WriteLine("listening");

            // инициализируем игру (ToDo: потом нужно это убрать в контроллер)
            game.Init(10, 5);

            // создаём бесконечный цикл чтобы слушать запросы с клиента
            while (true)
            {
                // контекст - это кто, что спросил, с какого IP, какой браузер итд - сопутствующие запросу данные
                // чтобы мы не парились с тем как нам возвращать данные на клиент по этому запросу, уже всё сделано за нас:
                // поскольку контекст содержит запрос (Request) и ответ (Response) мы можем просто положить чтото в response и это пойдёт на клиент

                // получаем контекст из слушателя - это происходит при любом запросе с клиента
                // (всмысле в этой точке программа ждёт запроса, цикл просто так не гоняется без дела)
                // когда запрос получен, выполняется эта строка: получаем контекст из слушателя
                HttpListenerContext context = listener.GetContext();
                // получаем запрос из контекста
                HttpListenerRequest request = context.Request;

                // чтобы не бегать по сложному объекту контекст, искать там запрос, доставать оттуда URL который пользователь ввёл в браузер, просто извлекаем его в переменную
                String rawurl = request.RawUrl;

                // сюда мы будем класть ответ сервера, неважно какая подсистема его сформирует
                String responsestring = "";

                // убираем / вначале, чтобы переиспользовать эту строку в нескольких местах
                String TrimmedURL = rawurl.TrimStart('/');

                // дальше идёт ветвление на MVC и просто файлы: если запрошен какойто файл, отдаём его. если нет точки в строке (признак расширения файла) то идём на MVC
                if (!rawurl.Contains('.'))
                {
                    ///MVC веточка

                    // что такое HTTPContext? поставьте туда мышку и нажмите F12 (или RMB -> Go To Definition)
                    // тупо три переменные сформированные в одну кучку - класс
                    // что делает функция GetContext - тоже можно посмотреть через F12:
                    // она URL вида Controller/Action/Parameters разбирает на части по разделителю '/' и складывает в нужные части с проверками есть они или нет
                    // не хотим париться как она это делает - выносим в отдельную функцию



                    HTTPContext ct = GetContext(TrimmedURL);

                    // если контекст удалось заполнить (хоть чтото)...
                    if (ct != null)
                    {
                        // ...начинаем изучать Reflection
                        // Reflection это способность среды исполнения CLR отвечать на вопросы программы о самой себе.
                        // получаем ссылку на ту сборку которая запрашивает информацию о самой этой сборке
                        Assembly asm = Assembly.GetCallingAssembly();

                        // ещё одна новая тема - лямбда-выражения.
                        // их особенность в том, что в качестве параметра им передаются не переменные, а алгоритмы (упакованные в анонимные функции)
                        // например:
                        // список (List) типов TypeInfo


                        // тут будет список всех типов из сборки, унаследованных от Controller
                        List <TypeInfo> Controllers =
                            // получается так:
                            // мы просим сборку (asm)
                            asm
                            // дать нам все определённые типы (defined types)
                            .DefinedTypes
                            // дальше одно и то же объяснение разными словами - каждая строчка объясняет одноитоже
                            // где (кагбэ функция без имени, которая принимает параметр и возвращает значение)
                            // Where (то что пришло => а это я верну)
                            // где (какойто входной аргумент типа TypeInfo (потому что List<TypeInfo>)) стрелка лямбды (=>) выражение которое возвращает да или нет (фильтр по которому ищем)
                            // где (инфа_о_типе => унаследован ли инфа_о_типе от класса Controller?).преобразовать к списку
                            // где (TypeInfo => является ли элемент BaseType переданного TypeInfo типом "Controller" приведённым к типу Type?).к списку
                            .Where(x => x.BaseType == typeof(Controller)).ToList();

                        // фух! сложно!
                        // вот так правильно, на уроке не получалось потому что подход мы использовали слишком простой
                        // вот так сложнее но эффективнее - можно класть типы в любую папочку и использовать для них любой namespace,
                        // Reflection через методы сборки подберёт их из самой сборки и правильно настроит
                        // вот магия Reflection!

                        // получаем имя сборки - как мы называемся?
                        AssemblyName an = asm.GetName();

                        // получаем полное имя класса вместе с namespace чтобы проблема папочек решалась автоматически
                        // имя класса с неймспейсом =  кого имя совпадает с тем что считается именем контроллера, пришедшим из браузера
                        String ClassName = Controllers
                                                               // список контроллеров, отфильтруй нам контроллеры по имени, которое совпадает с тем что в ct.Controller,
                                           .Where(x => x.Name == ct.Controller)
                                                               // и проконтролируй чтобы он там был, а если его там нет верни null
                                           .SingleOrDefault()? // внимание, ? означает что дальше идём только если тут чтото есть, если нет то следующая строка не будет выполняться. (сокращённая запись if != null)
                                                               // если в предыдущей строке не был результат null то берём из того что получили FullName - это и будет имя класса (fully-qualified name), например assembly.namespace.classname, или к примеру Server.MVC.Home
                                           .FullName;

                        // из имени класса и имени сборки создаём наш класс, завёрнутый в обслуживающую обёртку
                        ObjectHandle tclass = Activator.CreateInstance(an.Name, ClassName);

                        // получаем его тип (класс это сам класс например "Home" или "Game", а Type - это объект, который описывает этот класс, через него можно получить информацию об этом классе)
                        Type type = asm.GetType(ClassName);

                        // разворачиваем обёртку - получаем объект, созданный активатором из имени сборки и имени класса
                        object unwc = tclass.Unwrap();

                        //приводим развёрнутый объект к типу Controller чтобы иметь доступ к контексту, и чтобы компилятор мог проконтролировать это до исполнения
                        ((Controller)unwc).Context = ct;

                        // если указан какойто метод, который нужно выполнить, то выполняем его (он поумолчанию Index)
                        if (ct.Action != null)
                        {
                            // заполняем наш ответ тем, что вернёт метод контроллера (функция класса)
                            // просим тип вызвать (invoke) заданный метод для заданного объекта класса
                            // это так, потому что метод берётся из класса, а вызывается для объекта,
                            // поэтому методу Invoke нужно передать объект, для которого вызвать этот метод
                            // в конце приводим это всё к строке, потому что иначе компилятор не сможет проконтролировать тип
                            responsestring = type.GetMethod(ct.Action).Invoke(unwc, null).ToString();
                        }
                    }
                }
                else
                {
                    // веточка не MVC, старый тип запуска игр

                    // идём игроком (выполняем команду с клиента)
                    game.MoveUser(TrimmedURL);

                    // рендерим поле
                    String GameField = game.RenderField();

                    //получаем файл-шаблон для нашей игры
                    String tfile = GetFileContent("Game");

                    //заменяем там тэг "<game /> на отрендеренное игровое поле
                    tfile = tfile.Replace("<game />", GameField);

                    //заполняем строку вывода на клиент
                    responsestring = tfile;
                }

                // получаем ответ клиенту из контекста
                HttpListenerResponse response = context.Response;

                // буфер - чтобы можно было обрабатывать по частям, кодируем всё в UTF8
                byte[] buffer = Encoding.UTF8.GetBytes(responsestring);
                // сколько там букаф? осилим?
                response.ContentLength64 = buffer.Length;
                // получаем поток из ответа
                Stream output = response.OutputStream;
                // пишем в поток содержимое буфера
                output.Write(buffer, 0, buffer.Length);
                // закрываем поток
                output.Close();

                // выводим в консоль на всякий случай чтобы если на клиенте чтото пойдёт не так мы в консоли видели проблему
                Console.WriteLine($"String {responsestring} sent to client");
            }
        }