В этой статье я расскажу о том, зачем, почему и как я начал делать сайты на паскале: Delphi / FPC.
Вероятно, «сайт на паскале» ассоццируется с чем-то вроде:
writeln(‘Content-type: text/html’);
Но нет, всё гораздо интереснее! Впрочем, исходный код реального сайта (почти весь) доступен на GitHub.
Зачем?
Вообще я ни разу не профессиональный веб-разработчик — я делаю игры. А игре, особенно онлайновой, нужен сайт. Поэтому так сложилось, что я стал делать ещё и сайты для своих игр. Используя CGI на Perl — в начале/середине 2000-х это было популярно. Всё было хорошо, пока не возникла проблема.
В 2013 году мы начали проводить онлайн-турниры по игре «Спектромансер», для этого на сайте игры я сделал турнирную страничку, где показывается кому с кем играть, текущие результаты и т.п. В момент старта турнира страничка у игроков обновилась и… не загрузилась. Люди нажимали F5, чем ещё больше усугубляли проблему. Оказалось, что даже 4-5 запросов в секунду к CGI-скрипту, запускаемому в виде отдельного Perl-процесса, ощутимо замедляют сервер, а >10 запросов в секунду делают его совсем недоступным.
как написать вирус из 9 символов
Хорошо что этот стресс-тест состоялся во время репетиционного турнира: в дальнейшем я уже использовал для турниров обновляемую статическую страницу.
Почему?
Таким образом, когда возникла необходимость делать вот этот сайт для новой игры, возник вопрос — на чём? Тормозной CGI на Perl — не вариант. FastCGI на Perl? Не представляю как писать и отлаживать многопоточную программу на Perl, мне и с обычными-то скриптами проблем хватало. Node.js? Наверно это был бы наилучший выбор, если бы не некоторая неприязнь к JS.
А поскольку сама игра и её сервер написаны на паскале (на самом деле Delphi, но FPC тоже годится), возникла идея — а не сделать ли сайт на этом же языке? Это упростит интеграцию с сервером игры. «Попытка — не пытка!» — подумал я, и решил попробовать.
Как?
В качестве интерфейса выбрал SimpleCGI (SCGI): он несколько проще FastCGI, а преимущества последнего для меня неактуальны — нет необходимости разносить бэкенд на разные сервера, всё крутится на одном сервере. Так что задача свелась к разработке некоего SCGI-фреймворка, обрабатывающего запросы от сервера и генерирующего в ответ HTML-страницы из неких заготовок, шаблонов. В результате получился вот такой модуль-фреймворк. Он состоит из следующих частей:
- Главный цикл: принимает входящие соединения, считывает запросы и складывает их в очередь для обработки. Готовые ответы на обработанные запросы записывает в сокеты соединений и закрывает их.
- Рабочие потоки (N штук): достают запросы из очереди, парсят их заголовки и вызывают для исполнения пользовательские обработчики. У каждого worker’а — своё собственное постоянное подключение к БД.
- Система трансляции шаблонов: служит для генерации HTML-кода (или любого произвольного текста) путём рекурсивной трансляции шаблонов. Шаблоны грузятся из текстовых файлов.
- Набор вспомогательных функций: предназначен для использования обработчиками запросов (аналогично модулю CGI.pm в Perl). Получение параметров, установка куки и т.п.
Шаблоны
Весьма удобное свойство скриптов на Perl в том, что очень легко вносить небольшие изменения на сайт: просто подредактировал код скрипта — и все. Не нужно ничего компилировать, деплоить. Конечно, паскаль — язык компилируемый, тут так не выйдет, но все же я хотел иметь возможность по возможности вносить изменения без перезапуска процесса. Поэтому я постарался сделать систему шаблонов достаточно гибкой.
Я сделал сайт за 10 минут!
Работает она так. В папке «templates» лежат файлы шаблонов: они загружаются при запуске процесса а также перезагружаются при изменении — таким образом можно изменять динамический контент не перезапуская процесс. В каждом файле может быть один или несколько шаблонов. Все вместе они образуют словарь (или хэш) шаблонов: «значение»>.
Это статический словарь шаблонов — он общий для всех запросов и его содержимое неизменно (пока не изменится содержимое файлов). Есть ещё второй — динамический словарь, он создаётся пустым для каждого запроса и заполняется обработчиком динамическими данными — например из БД. Комбинируя статические и динамические данные и формируется итоговый результат.
Пример декларации шаблона:
#NEWSFEED_ITEM: [TOP] $NEWS_DATE $NEWS_TITLE $COMMENTS
Это статический шаблон записи в ленте новостей с именем NEWSFEED_ITEM, внутри он содержит включения нескольких других шаблонов, например NEWS_TEXT — динамический шаблон, содержащий текст новости, загруженный из БД. Трансляция заключается в том, что все подстроки вида $ИМЯ_ШАБЛОНА рекурсивно заменяются на значение этого шаблона.
Здесь можно также заметить псевдотэг для условной трансляции: — в процессе трансляции такие тэги удаляются а их содержимое оставляется либо также удаляется — в зависимости от значения указанного шаблона. Я специально выбрал такой формат условий — в виде HTML-тэгов, чтобы при редактировании в текстовом редакторе работала подсветка синтаксиса и чтобы было легко видеть парный тэг.
Код формирования ленты новостей, использующий этот шаблон, выглядит примерно так:
result:=»; // Для каждой новости выполняем трансляцию шаблона NEWSFEED_ITEM и складываем всё в строку result for i:=0 to n-1 do begin id:=StrToIntDef(sa[i*c],0); title:=sa[i*c+1]; cnt:=StrToIntDef(sa[i*c+2],1)-1; flags:=StrToIntDef(sa[i*c+3],0); // запрашиваем текст и дату новости db.Query(‘SELECT msg,created FROM messages WHERE topic=%d ORDER BY id LIMIT 1’, [id]); if db.lastErrorCode<>0 then continue; text:=db.Next; date:=db.NextDate; // Заполняем динамические шаблоны (словарь temp) temp.Put(‘NEWS_ID’,id,true); temp.Put(‘NEWS_DATE’,FormatDate(date,true),true); temp.Put(‘NEWS_TITLE’,title,true); temp.Put(‘NEWS_PINNED’,flags and 4>0,true); comLink:=’$LNK_READ_MORE | ‘; if cnt>0 then comLink:=comLink+inttostr(cnt)+’ $LNK_COMMENTS’ else comLink:=comLink+’$LNK_LEAVE_COMMENT’; temp.Put(‘NEWS_TEXT’,text,true); temp.Put(‘COMMENTS’,comLink,true); // Выполняем трансляцию шаблона result:=result+BuildTemplate(‘#NEWSFEED_ITEM’); end;
Локализация
Шаблоны также удобно использовать для локализации. Для этого используется глобальная (в контексте запроса) переменная clientLang. Работает это так: если обработчик запроса выясняет, что клиенту нужна страница на русском языке — он записывает в clientLang значение «RU», после чего транслятор шаблонов, обнаружив в тексте $ИМЯ_ШАБЛОНА, всегда пытается сперва применить $ИМЯ_ШАБЛОНА_RU. Таким образом, для локализации нужно всего лишь для каждого шаблона с текстом создать его вариант для другого языка:
#TITLE_NEWS:News #TITLE_NEWS_RU:Новости
Пример использование фреймворка
Пример кода простого сайта:
program website; uses SysUtils, SCGI; // Обработчик запроса главной страницы function IndexPage:AnsiString; stdcall; begin result:=FormatHeaders(‘text/html’)+BuildTemplate(‘#INDEX.HTM’); end; begin SetCurrentDir(ExtractFileDir(ParamStr(0))); SCGI.Initialize; // Загрузка конфига AddHandler(‘/’,IndexPage); // Устанавливаем обработчик для запроса ‘/’ SCGI.RunServer; // запускаем рабочие потоки и главный цикл end.
Итого
Описываемый фреймворк я написал в процессе создания реального сайта astralheroes.com в конце 2015 года. Как это обычно бывает, первый блин вышел немножко комом — код получился несколько сумбурным и запутанным, следующий сайт получается уже лучше. Тем не менее, и процессом и результатом я доволен: сайт работает хорошо, легко отлаживается и обновляется.
- Я ожидал, что по сравнению с компактным Perl код сайта сильно раздуется, но нет — та же функциональность, написанная на паскале, занимает лишь примерно вдвое больше, чем на Perl. Но при этом выглядит более понятно.
- Радует отладка! Perl — замечательный язык, если нужно написать что-то в пределах 100 строк, такое, что не требует отладки. Но как только нужно сделать что-то более-менее сложное — отладка превращается в кошмар. В Delphi же заниматься отладкой легко и удобно.
- Часть функционала сайта осталась на Perl. Потому что во-первых, часть функций осталась неизменной с предыдущего сайта, поэтому нет смысла переписывать то, что уже написано и исправно работает. А во-вторых, некоторые некритичные к скорости вещи гораздо проще реализовать на Perl, если там для этого есть готовая библиотека, а на паскале её нет.
- Работать с шаблонами довольно удобно: они позволяют структурировать сайт, разбить его на отдельные блоки, избегать дублирования текста. И еще упрощают локализацию.
- Радует производительность. Ведь я экономлю время не только на запуске процессов, загрузке библиотек, подключении к БД (что само по себе немаловажно), но и имею возможность сохранять контекст, глобальные данные и использовать их для обработки множества запросов. Например, для реализации поиска по форуму используется глобальный индекс, который постоянно доступен в памяти — не нужно ничего грузить из БД. Данные рейтинга игроков также кэшируются.
В целом высокая производительность позволила не напрягаясь сделать на форуме подсветку названий игровых карт, чтобы можно было навести на них мышь и посмотреть описание карты. При этом название в тексте может быть написано неточно — для определения соответствия используется расстояние Левенштейна. Например, на этом скриншоте в названии карты отличаются две буквы:
Так где же исходники сайта?
Обратите внимание, что в репозитории есть подмодуль, поэтому клонировать лучше с параметром «—recursive».
Проект сайта находится в файле: «AH-WebsiteBackendsrcwebsite.dpr»
Это не совсем полная копия действующего сайта: понятно, что я не могу опубликовать содержимое БД с данными игроков, я также не публикую CGI-скрипты, поскольку они не имеют отношения к описываемой теме. Тем не менее, проект собирается, запускается и работает, полностью демонстрируя работу фреймворка.
Публикация кода сайта, а также кода движка, который он использует, стала возможной благодаря поддержке, которую я получил на Patreon. Выражаю благодарность всем поддержавшим, и призываю присоединиться — впереди ещё много интересного 🙂
Источник: habr.com
Конвертер из Pascal в HTML — PascalABC.NET
Написал программу на паскале, можно ли ее как нибудь конвертировать в html?
Код к задаче: «Конвертер из Pascal в HTML»
Листинг программы
program apashtm; uses UPasHtm; begin if paramcount < 2 then writeln(paramstr(0),’ in.pas out.html’) else ConvertPasToHtm(paramstr(1),paramstr(2)) end.
7 голосов , оценка 4.143 из 5
Похожие ответы
- Связные списки, переписать код с использованием Case
- Рекурсия: вычислить количество четных элементов массива
- Реализовать навигацию по пунктам меню
- Как перенести значение из одной процедуры в другую?
- Ошибка при объявлении размера массива: «неизвестное имя ‘n'»
- Нет перегруженной подпрограммы с такими типами параметров
- Напишите функцию, которая заменяет во всей строке все римские числа на соответствующие десятичные числа
- Вычислить выражение, состоящее из трех чисел
- Вычислить максимальный по модулю элемент массива (рекурсивной функцией)
- Найти и напечатать номера столбцов матрицы, сумма элементов которых попадает в заданный интервал
- Переход с одной формы на другую (Кнопка(пункт меню) стоит на Form1 в Unit1. Перейти надо на Form2 в Unit2
Все виды студенческих работ на заказ
Источник: studassistent.ru
Оформление текста на экране в Паскаль
Оформление и разметку текста используют довольно редко , однако бывают случаи , когда они вам пригодятся.
Возможно , когда-нибудь вы столкнетесь с такой задачей : как оформить текст в паскале.
В данной статье вы узнаете о том , как изменить цвет текста , как добавить цветной фон , как очистить экран и т.д.
Модуль crt
Для всех ниже приведенных функций требуется подключать дополнительный модуль crt. Подключать его нужно в блоке uses :
program mypascal;
uses crt;
Если вы не подключите данный модуль , то функции по оформлению текста не будут работать.
После того , как вы его подключите , программа будет работать в новом окне размером 80×25. Представлять такое окно можно как таблица в 25 строк и 80 столбцов.
GotoXY
Когда мы выводим текст на экран , то курсор находится в координате 1,1 ( столбец-1 , строка-1 ). Но для того , чтобы изменить место положение выводимого текста , в паскале предусмотрена функция gotoxy.
program mypascal;
uses crt;
begin
gotoxy(25,5);
writeln(‘Hello’);
end.
TextColor
Стандартно , в языке программирования паскаль текст выводится строго черным цветом , но его также можно изменить. Изменить цвет текста можно командой textcolor. Чтобы изменить цвет текста требуется использовать команду textcolor(red) , а в скобках указать цвет ( например red ). В скобках можно использовать название цвета , а также код цвета.
Но стоит помнить , что команда textcolor не меняет весь текст на экране ,а только тот , который выводится после этой команды.
program mypascal;
uses crt;
begin
writeln(‘Hello’);
textcolor(green);
writeln(‘Hello’);
end.
Результат выполнения данной программы будет выглядеть примерно так :
Clrscr
Функция clrscr стирает весь текст , который был выведен на экран до использования данной функции. Также с помощью неё можно закрасить экран в определенный цвет. О том как это сделать читайте далее.
TextBackGround
Тексту также можно задавать цвет фона. Фон для текста задается командой textbackground. В скобках , в аналогии с textcolor можно указывать имя или код цвета.
program mypascal;
uses crt;
begin
writeln(‘Hello’);
textbackground(green);
writeln(‘Hello’);
end.
Результат выполнения данной программы будет выглядеть так :
С помощью данной команды можно задать фон всему рабочему окну программы,
Сделать это можно так :
program mypascal;
uses crt;
begin
textbackground(green);
clrscr;
writeln(‘Hello’);
writeln(‘Hello’);
end.
В данном случае всё окно рабочей программы будет окрашено в зеленый цвет.
Delay
С помощью команды delay можно остановить программу на определенное количество времени . Это время указывается в скобках в мкс.
program mypascal;
uses crt;
begin
delay(1000);
writeln(‘Hello’);
end.
В данном случае на экран будет выведено сообщение «hello» с задержкой 1000 мкс.
Источник: mypascal.ru