Hard Code Golf: создать чат

13

Cue Storyline: это начало 21-го века, и большинство вещей ушли в прошлое. Тем не менее, вы и ваши коллеги-разработчики кода стремитесь воссоздать 90-е годы. В рамках этой задачи вы должны воссоздать минималистичный чат.

Цель: создать чат с как можно меньшим количеством байтов. Программы, которые вы пишете, должны функционировать как простой сервер, который обслуживает веб-страницу, которая позволяет пользователям размещать текст на экране.

Фактическая цель: фактически разместить рабочий чат с вашего компьютера. Вам не нужно этого делать, но так намного веселее.

Требования:

  • Пользователи должны быть в состоянии дать себе имя пользователя, которое длится для сеанса
  • Пользователи должны иметь возможность многократно печатать и отправлять текст, который будет отображаться другим пользователям.
  • Каждый пользователь должен иметь возможность видеть текст, представленный всеми пользователями, вместе с именами отправителей, и информация должна отображаться в хронологическом порядке.
  • На странице также должно отображаться количество людей в сети и список их имен
  • Ваш чат должен быть доступен любому человеку в Интернете, который знает, где его найти (например, знает IP-адрес).
  • Он должен функционировать в современных веб-браузерах.

Все остальное зависит от вас!

Материалы:

  • Должен включать исходный код или ссылку на исходный код
  • Должны включать скриншоты функционального чата
  • Должен включать общий размер в байтах всех написанных вами программ / файлов, необходимых для его работы.

Эта задача была в песочнице некоторое время, так что, надеюсь, все изломы были решены.

PhiNotPi
источник
1
было бы допустимо, если бы мы заставляли участников чата набирать каждый из их ответов в течение девяти секунд?
Джон Дворжак
Я думаю, что 9 секунд, вероятно, слишком мало. Впрочем, что-то вроде 99 секунд может сработать. Я никогда не думал о том, чтобы ограничивать время для болтунов.
PhiNotPi
определить "онлайн". Нужно ли публиковать сообщения перед выгрузкой, хватит ли 5с таймаута, или нам даже разрешено требовать, чтобы люди никогда не выходили из системы?
Джон Дворжак
Разрешено ли нам разрешать HTML-инъекцию и другие вещи, которые могут нарушить работу чата (при условии, что мы не навредим нашему компьютеру)?
Джон Дворжак
На самом деле, вы можете уточнить, "введите каждый из их ответов в течение девяти секунд?" Под «онлайн» я подразумеваю список людей, которые в настоящее время просматривают чат-комнату, например, если чат-комната открыта в окне браузера. Тайм-аут будет в порядке.
PhiNotPi

Ответы:

18

PHP + JQuery + HTML + CSS, 1535 байт

Это представление больше склоняется к тому, что ФП считает «фактической целью». Это полнофункциональный чат-сервер, который может быть размещен практически на любом веб-сервере.

Функциональность включает в себя:

  • Уведомления, когда пользователи входят или выходят из чата.
  • Уведомления, когда пользователи меняют свой псевдоним.
  • Опрос в режиме реального времени для новых сообщений, без создания избыточного трафика сервера или нагрузки на сервер.
  • Макет и удобство использования очень напоминают существующие клиенты чата, такие как X-Chat.

Чтобы стать сеансом, введите псевдоним в соответствующем поле и нажмите Tabили Enterдля отправки. Если псевдоним уже используется, вы будете уведомлены. Отправка сообщений также осуществляется через Enter.

Для вашего удобства архив всех файлов можно найти здесь: chat.zip (выберите «Загрузить» в меню «Файл»). Для установки распакуйте в веб-каталог на любом сервере с PHP 5.4 или выше.

Предостережения:

  • IE 8 или ниже будет вращаться в бесконечный цикл при опросе, потому что по какой-то неизвестной человечеству причине все Ajax-запросы кэшируются по умолчанию. Это также не позволяет вам отправлять одно и то же сообщение дважды и правильно обновлять список пользователей. Это можно исправить, добавивcache:false к каждому запросу Ajax.
  • Во всех версиях IE сообщения не будут отправляться нажатием Enter, поскольку changeсобытие не вызывается (однако нажатие Tab работает). Это можно исправить, добавив onkeypressобработчик, проверив, был ли ключ Enter, а затем вызвав $(v).blur().focus().

Короче говоря, IE не поддерживается.


клиент

Расположение элементов может быть немного более надежным, но оно должно выглядеть хорошо с минимальным размером окна около 800x600.

chat.htm (190 байт)

<script src=jquery.min.js></script>
<script src=c.js></script>
<link rel=stylesheet href=c.css>
<select id=u multiple></select><pre id=o></pre>
<input id=n onchange=u()><input id=v onchange=s()>

ccc (136 байт)

i{color:#999}
#u{float:right;height:100%;width:200px;margin-left:10px}
#o{border:1px solid #999;height:93%;overflow-y:scroll}
#v{width:54%}

c.js (435 байт)

var l
(function p(){
  $.ajax({url:'p.php',data:{n:$('#n').val()},success:function(d){
    $('#o').html(d).scrollTop(1e4);$('#u').load('n.php');
  },complete:p,timeout:2e4})
})()
function s(){
  $.get('s.php',{n:$(n).val(),v:$(v).val()})
  $(v).val('')
}
function u(){
  $.get('u.php',{l:i=l,n:l=$(n).val()}).fail(function(){
    alert("This name is already in use!")
    $(n).val(l=i)
  })
}
$(window).on('unload',function(){$.ajax({url:'l.php',data:{l:l},async:false})})

сервер

Я прошу прощения за то, что сервер был разбит на множество крошечных кусочков. Альтернативой может быть использование адекватного протокола сообщений (через JSON-кодирование / декодирование) или наличие большогоif ... elseif ... соответствии с пост-переменных. Создание отдельных скриптов, просто запрос из того, что вам нужно, намного короче и, возможно, проще, чем оба.

o.php (119 байт) O ручки , как подключение к базе данных «»

<?$m=array_slice(unserialize(file_get_contents(m)),-300);
$u=unserialize(file_get_contents(u));$t=time();extract($_GET);

c.php (57 байт). C пропускает изменения в «базе данных».

<?foreach([u,m]as$c)file_put_contents($c,serialize($$c));

p.php (151 байт) P ОЛЛС для новых сообщений

<?for($t=time();@filemtime(m)<$t;usleep(1e3))clearstatcache();include('o.php');
foreach($m as$v)if($n&&$v[0]>=$u[$n])echo@date("[H:i]",$v[0])."$v[1]\n";

s.php (62 байта) S завершить сообщение на сервер

<?include('o.php');$m[]=[$t,"<b>$n</b>: $v"];include('c.php');

u.php (222 байт) U регистрации Ser или изменить псевдоним

<?include('o.php');if(!trim($n)||$u[$n])exit(header('HTTP/1.1 418'));
$m[]=[$t,$u[$l]?
"<i><b>$l</b> is now known as <b>$n</b>.</i>":
"<i><b>$n</b> has entered the chat.</i>"];
$u[$n]=$u[$l]?:$t;unset($u[$l]);include('c.php');

n.php (65 байт) Возвращает список пользователей н Эймс

<?include('o.php');foreach($u as$k=>$v)echo"<option>$k</option>";

l.php (98 байт) Пользователь имеет л EFT (закрыли их браузер)

<?include('o.php');$m[]=[$t,"<i><b>$l</b> has left the chat.</i>"];
unset($u[$l]);include('c.php');
Примо
источник
Я думаю, что вы можете обойтись onchange=uбез скобок. Однако вы не получите согласованного контекста, но он вам все равно не нужен.
Джон Дворак
Можете ли вы сделать учебник немного более подробным? Я хочу установить это на Mac.
Хайкам
@Peanut Я набрал несколько инструкций: codepad.org/UKGwb4g2 . Я работаю вслепую, но это, вероятно, сработает.
Примо
13

Питон, 230

Это довольно минимально, но, похоже, на высоте. Пользователи считаются «просматривающими страницу», если они общались в чате в течение последних 99 секунд.

import cherrypy as S,time
@S.quickstart
@S.expose
def _(n='',p='',l=["<form%sn value='%s'%sp%s'' type=submit>"],u={},t="><input name="):u[n]=time.time();l+=p and[n+':'+p];return'<br>'.join([k*(u[n]-99<u[k])for k in u]+l)%(t,n,t,t)

Это использует один из моих самых любимых трюков в Python: значения по умолчанию - это просто ссылки на то, что вы передали. Если это изменчивый объект, он просто приходит на прогулку.

Другой, которым я редко пользуюсь - карри!

Запуск сервера:

Запустите скрипт чата из python (например, python chat.py), а затем укажите в браузере http://localhost:8080что-то вроде

Скриншот

Python, 442

Этот на самом деле приятно использовать. Это гольф, поэтому я считаю это менее удовлетворительным решением. Теперь я использую iframe и форму с обработкой клавиш ... и мета-обновлением для опроса нового контента.

import time,cherrypy as S
class C:
 c=S.expose(lambda s:"<form action=w target=t method=post><input name=n><input name=p onkeyup='if(event.keyCode==13){this.form.submit();this.value=\"\"}'><br><iframe name=t width=640>")
 @S.expose
 def w(s,n='',p='',l=[],u={}):u[n]=time.time();l+=p and[n+':'+p];return'<meta http-equiv=refresh content="1;url=w?n=%s">'%n+','.join(k for k in u if(u[n]-9<u[k])*k)+'<hr>'+'<br>'.join(l[::-1])
S.quickstart(C())

версия 2

Бутби
источник
2
Я сомневаюсь, что могу указать свой браузер http://localhost:8080/c и получить доступ к вашему HTTP-серверу
Джон Дворжак
1
@JanDvorak Вот почему я не сделал эту ссылку.
Boothby
1
Для тех, у кого уже есть служба, работающая через порт 8080, вы можете добавить следующее, чтобы использовать другой порт:S.config.update({'server.socket_port':8090})
primo
Насколько сложно будет обновить окно чата, когда кто-то отправляет новое сообщение, а не только пользователь? (В его текущей форме, чтобы проверить, есть ли какие-либо новые сообщения, вам нужно отправить пустое сообщение до того, как обновится ваше окно.)
primo
1
@primo Правильно! Вот как вы проверяете, сказали ли люди что-то. Задача говорит о воссоздании 90-х годов. И тогда ожидать, что ваши пользователи примут интерфейс, предложенный простейшим кодом, было по-прежнему круто. HP дала нам RPN, и нам понравилось . Думая как 201 * -er, вы получаете 1280 персонажей.
Boothby
5

Метеор: 575 символов

Мне было очень весело с этим! Приложение работает по адресу http://cgchat.meteor.com/ .

chat.html: 171 символов

<body>{{>b}}</body><template name="b">{{#if l}}Online: {{#each u}}{{n}}, {{/each}}<hr>{{#each m}}{{n}}: {{t}}<p>{{/each}}<hr><input>{{else}}Name: <input>{{/if}}</template>

lib / chat.js: 45 символов

c=Meteor.Collection;u=new c('u');m=new c('m')

client / client.js: 359 символов

j=$.now;s=Session;t=Template.b;t.events({'change input':function(){v=$('input').val();s.get('u')?(m.insert({n:s.get('u'),t:v}),u.update(u.findOne({n:s.get('u')})._id,{$set:{l:j()}})):(s.set('u',v),u.insert({n:v,l:j()}))}});t.l=function(){return !!s.get('u')};t.u=function(){return u.find({l:{$gt:(j()-20000)}}).fetch()};t.m=function(){return m.find().fetch()}
Питер Бос
источник
Ссылка сейчас мертва.
programmer5000
5

Узел / Метеор JavaScript + HTML + CSS + веб-сокет: 1,105 байт

Вот один из них, использующий node.js / meteor . Очевидно написано в js, в реальном времени и с использованием веб-сокетов. Использует встроенные в метеор пакеты по умолчанию.

Это может быть намного меньше. Кроме того, он постоянен благодаря включенному монго (не то, чтобы это было хорошо).

Рабочий скриншот:

введите описание изображения здесь

Для выполнения установите Метеор.

Linux:

curl https://install.meteor.com | /bin/sh`

Windows: win.meteor.com

Клонируйте мой репо и выполните метеорит:

git clone http://github.com/bradgearon/meteor-chat
cd meteor-chat
meteor

укажите ваш браузер на localhost: 3000

chat.js: 703 байта (клиент / сервер):

l='subscribe',d=[],n='n',i='i',b='b',c='click #',r='return ',u='u',y=0
f=Function,m=Meteor,o=m.Collection,p=new o(b),t=new o(u)
w=f('t.remove({i:d.pop()})'),g=f('_(d.length).times(w)')
m.isClient&&(h=Template.h,e=h.events={},m[l](b),m[l](u),s=Session,
w=f(r+'s.get(i)'),h.p=f(r+'p.find()'),h.t=f(r+'t.find()'),a=f('a','a','y=$("#3").val(),s.set(i,1)'),
e[c+'2']=f('p.insert({c:(y||"?")+": "+$("#l").val()})'),
e[c + '4'] = f('w()||m.call("x",$("#3").val(),t._connection._lastSessionId,a)')
)||(
m.startup(f('t.remove({}),p.remove({}),m.setInterval(g,100)')),j=f('h=this.id;h&&d.push(h)'),
m.methods({x:f('k','d','s=m.default_server.sessions[d].socket,s.on("close",j),t.insert({n:k,i:s.id})')}))

chat.css: 132 байта

g{display:block;overflow-y:scroll;margin:10px;}
n{float:right;width:40%;min-height:100%;}
d{float:left;width:60%;min-height:100%;}

chat.html: 270 байт

<body>
    {{> h}}
</body>
<template name="h">
<d>
<g>{{#each p}}{{c}}<br />{{/each}}</g>
<input id=l>{{this.k}}</input>
<input type=submit id=2 />
</d>
<n>
<g>{{#each t}}{{n}}<br />{{/each}}</g>
<input id=3 />
<input type=submit id=4 />
</n>
</template>
beeradg
источник
1
Добро пожаловать в Codegolf! Этот файл, chat.htmlкажется, имеет только 254 байта. Обратите внимание, что браузеры не очень требовательны - я не пытаюсь закрывать теги, и вам определенно не нужна косая черта в конце тегов (если это не требуется узлу?). Кроме того, убейте больше пробелов! Я вижу пару в javascript, и слишком много в html.
Boothby