Hard Code Golf: Створіть чат


13

Сюжетний сюжет: На початку 21 століття, і більшість речей стали минулим. Ви та ваші колеги з кодом-гольф-їдальцями, однак, намагаєтесь відремонтувати 1990-ті. У рамках цього виклику ви повинні відтворити мінімалістичний чат.

Мета: Створити чат з якомога менше байтів. Програма, яку ви пишете, має функціонувати як простий сервер, який обслуговує веб-сторінку, яка дозволяє користувачам розміщувати текст на екрані.

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

Вимоги:

  • Користувачі повинні мати можливість дати собі ім’я користувача, яке триває до сеансу
  • Користувачі повинні мати можливість неодноразово вводити та надсилати текст, який буде відображатися іншим користувачам
  • Кожен користувач повинен мати можливість бачити текст, який подають усі користувачі, а також імена користувачів, що надсилаються, а інформація повинна відображатися в хронологічному порядку
  • На сторінці також повинно бути відображено кількість людей в Інтернеті та список їх імен користувачів
  • Ваша балачка повинна бути доступною для всіх в Інтернеті, хто знає, де її знайти (наприклад, знаючи IP-адресу).
  • Він повинен функціонувати в сучасних веб-браузерах.

Все інше залежить від вас!

Подання:

  • Слід включити вихідний код або посилання на вихідний код
  • Потрібно включати скріншоти функціональної чатової кімнати
  • Потрібно включати загальний розмір у байтах усіх написаних вами програм / файлів, необхідних для роботи.

Цей виклик вже деякий час знаходиться в пісочниці, тому, сподіваємось, всі переробки були відпрацьовані.


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()>

c.css (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 байт) Отримує список користувачів n ames

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

l.php (98 байт) Користувач має l 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щоб побачити щось подібне

скріншот

Пітона, 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 Ось чому я не зробив це посилання.
кабінка

1
Для тих, хто вже має службу, що працює на порту 8080, ви можете додати наступне використання іншого порту:S.config.update({'server.socket_port':8090})
прим

Наскільки складно було б оновити вікно чату, коли хтось надсилає нове повідомлення, а не лише користувач? (У його поточній формі, щоб перевірити, чи є якісь нові повідомлення, вам потрібно надіслати порожнє повідомлення перед оновленням вашого вікна.)
прим

1
@primo Право! Ось так ви перевіряєте, чи люди щось сказали. Проблема сказала відновити 90-ті. І тоді, очікуючи, що ваші користувачі приймуть інтерфейс, запропонований найпростішим кодом, було все ще круто. HP подарувала нам RPN, і нам це сподобалось . Якщо ви думаєте, що 201 * -er, ви отримуєте 1280 символів.
кабінка

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()}

Посилання тепер мертва.
програміст5000

5

Вузол / Meteor javascript + html + css + websocket: 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>

1
Ласкаво просимо до codegolf! chat.htmlЗдається, цей файл містить лише 254 байти. Зауважте, що браузери не дуже прискіпливі - я не намагаюся закривати теги, і вам точно не потрібна коса риса в кінці тегів (якщо цього не вимагає вузол?). Крім того, вбийте більше пробілів! Я бачу пару в JavaScript, і занадто багато в html.
кабінка
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.