Hard Code Golf: crea una chat room


13

Cue Storyline: è l'inizio del 21 ° secolo e molte cose sono diventate un ricordo del passato. Tu e i tuoi compagni di golfisti, tuttavia, siete in cerca di ricostruire gli anni '90. Come parte di questa sfida, è necessario ricreare una chat room minimalista.

L'obiettivo: creare una chat room con il minor numero di byte possibile. I programmi che scrivi devono funzionare come un semplice server, che serve una pagina web, che consente agli utenti di pubblicare testo sullo schermo.

L'obiettivo effettivo: ospitare effettivamente una chat room funzionante dal proprio computer. Non devi farlo, ma è molto più divertente in questo modo.

Requisiti:

  • Gli utenti dovrebbero essere in grado di assegnarsi un nome utente che dura per la sessione
  • Gli utenti dovrebbero essere in grado di digitare e inviare ripetutamente il testo, che verrà visualizzato ad altri utenti
  • Ogni utente dovrebbe essere in grado di vedere il testo inviato da tutti gli utenti, insieme ai nomi utente dei mittenti e le informazioni dovrebbero essere visualizzate in ordine cronologico
  • La pagina dovrebbe anche visualizzare il numero di persone online e un elenco dei loro nomi utente
  • La chat room dovrebbe essere accessibile a chiunque su Internet sappia dove trovarla (come conoscere l'indirizzo IP).
  • Dovrebbe funzionare nei browser Web moderni.

Tutto il resto dipende da te!

osservazioni:

  • Dovrebbe includere il codice sorgente o un collegamento al codice sorgente
  • Dovrebbe includere schermate della chat room funzionale
  • Dovrebbe includere la dimensione totale, in byte, di tutti i programmi / file che hai scritto che sono necessari per farlo funzionare.

Questa sfida è nella sandbox da un po 'di tempo, quindi speriamo che tutti i nodi siano stati risolti.


1
sarebbe ammissibile se costringessimo i chatter a digitare ciascuna delle loro risposte entro nove secondi?
John Dvorak,

Penso che 9 secondi sia probabilmente troppo breve. Qualcosa come 99 secondi potrebbe probabilmente funzionare, però. Non ho mai pensato di fissare limiti di tempo alle chiacchiere.
PhiNotPi

definire "online". Dobbiamo ripubblicare prima di scaricare, il timeout di 5s sarà sufficiente o ci è consentito persino rivendicare che le persone non si disconnettono mai?
John Dvorak,

siamo autorizzati a consentire l'iniezione HTML e altre cose che potrebbero interrompere la chat (purché non danneggiamo il nostro computer)?
John Dvorak,

In realtà, puoi chiarire "digita ciascuna delle loro risposte entro nove secondi?" Per "online" intendo un elenco di persone che stanno attualmente visualizzando la chat room, ad esempio aprendo la chatroom in una finestra del browser. Un timeout andrà bene.
PhiNotPi il

Risposte:


18

PHP + JQuery + HTML + CSS, 1535 byte

Questa è una proposta che tende maggiormente a ciò che l'OP ha ritenuto "l'obiettivo effettivo". Cioè, un server di chat completamente funzionale, che può essere ospitato su qualsiasi server Web ovunque.

La funzionalità include:

  • Notifiche quando gli utenti accedono o escono dalla chat room.
  • Notifiche quando gli utenti cambiano il loro alias.
  • Polling in tempo reale per nuovi messaggi, senza generare traffico del server in eccesso o carico del server.
  • Layout e usabilità che ricordano fortemente i client di chat esistenti, come X-Chat.

Per essere una sessione, inserisci un alias nella casella appropriata e premi Tabo Enterper inviare. Se l'alias è già in uso, riceverai una notifica. Anche l'invio di messaggi avviene tramite Enter.

Per comodità, è possibile trovare un archivio di tutti i file qui: chat.zip (scegliere Scarica dal menu File). Per l'installazione, decomprimere in una directory Web su qualsiasi server che esegue PHP 5.4 o versioni successive.

Avvertenze:

  • IE 8 o inferiore girerà in un ciclo infinito durante il polling, perché per qualche ragione sconosciuta all'umanità, tutte le richieste Ajax sono memorizzate nella cache per impostazione predefinita. Ti impedisce inoltre di inviare lo stesso messaggio due volte e di aggiornare correttamente l'elenco utenti. Questo potrebbe essere risolto aggiungendocache:false ad ogni richiesta Ajax.
  • In tutte le versioni di IE, i messaggi non verranno inviati premendo Invio, poiché l' changeevento non viene attivato (premendo Tab, tuttavia, funziona). Ciò potrebbe essere risolto aggiungendo un onkeypressgestore, controllando se la chiave era Invio e quindi chiamando $(v).blur().focus().

In breve, IE non è supportato.


Cliente

Il posizionamento degli elementi potrebbe essere un po 'più robusto, ma dovrebbe apparire a posto con una dimensione minima della finestra di circa 800x600.

chat.htm (190 byte)

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

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

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

server

Mi scuso per il fatto che il server sia stato suddiviso in così tanti piccoli pezzi. L'alternativa sarebbe quella di utilizzare un protocollo di messaggio adeguato (tramite codifica / decodifica JSON) o avere un grandeif ... elseif ... secondo il quale sono presenti le variabili post. Realizzare script separati, solo una richiesta da quello di cui hai bisogno è molto più breve e forse più semplice di entrambi.

o.php (119 byte) O pen come connessione al 'database'

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

c.php (57 byte) C ommits cambia in "database"

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

p.php (151 byte) P olls per nuovi messaggi

<?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 byte) S termina un messaggio al server

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

u.php (222 bytes) U registrazione servizi o cambiamento alias

<?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 byte) Recupera l'elenco di utenti n ames

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

l.php (98 bytes) L'utente ha l EFT (chiuso browser)

<?include('o.php');$m[]=[$t,"<i><b>$l</b> has left the chat.</i>"];
unset($u[$l]);include('c.php');

Penso che tu possa fare a onchange=umeno delle parentesi. Non otterrai un contesto coerente, tuttavia, ma non ti serve comunque.
John Dvorak,

Puoi rendere il tutorial un po 'più dettagliato? Voglio configurarlo su un Mac.
Hayakam,

@Peanut Ho scritto alcune istruzioni: codepad.org/UKGwb4g2 . Sto lavorando alla cieca, ma probabilmente funzionerà.
primo

13

Python, 230

Questo è abbastanza minimale, ma sembra essere all'altezza delle specifiche. Gli utenti vengono considerati "visualizzazione della pagina" se hanno chattato negli ultimi 99 secondi.

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)

Questo utilizza uno dei miei trucchi preferiti in Python: i valori predefiniti sono solo riferimenti a qualunque cosa tu abbia passato. Se è un oggetto mutevole, arriva solo per il giro.

Un altro che non riesco a usare spesso: il curry!

Esecuzione del server:

Esegui lo script della chat da Python (ad esempio python chat.py) e quindi punta il browser verso http://localhost:8080per vedere qualcosa di simile

immagine dello schermo

Python, 442

Questo è davvero bello da usare. Questo è il golf, quindi considero questa una soluzione meno soddisfacente. Ora, abuso di un iframe e un modulo con gestione delle chiavi ... e un meta-aggiornamento per sondare nuovi contenuti.

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

versione 2


2
Dubito di poter puntare il mio browser verso http://localhost:8080/c e accedere al tuo server HTTP
John Dvorak il

1
@JanDvorak Ecco perché non ho creato un collegamento.
stand,

1
Per coloro che hanno già un servizio in esecuzione sulla porta 8080, è possibile anteporre quanto segue per utilizzare una porta diversa:S.config.update({'server.socket_port':8090})
primo

Quanto sarebbe difficile aggiornare la finestra di chat quando qualcuno invia un nuovo messaggio e non solo l'utente? (Nella sua forma attuale, per verificare se ci sono nuovi messaggi, è necessario inviare un messaggio vuoto prima di aggiornare la finestra.)
primo

1
@primo Bene! È così che controlli per vedere se le persone hanno detto qualcosa. Il problema diceva di rievocare gli anni '90. E allora, aspettarsi che gli utenti accettassero l'interfaccia suggerita dal codice più semplice era ancora bello. HP ci ha dato RPN e ci è piaciuto . Pensare come un 201 * -er ti dà 1280 personaggi di gonfiore.
stand

5

Meteora: 575 caratteri

Mi sono divertito molto con questo! L'applicazione è in diretta su http://cgchat.meteor.com/ .

chat.html: 171 caratteri

<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 caratteri

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

client / client.js: 359 caratteri

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

Il link ora è morto.
programmatore

5

Nodo / Meteor javascript + html + css + websocket: 1.105 byte

Eccone uno che usa node.js / meteor . Ovviamente scritto in js, in tempo reale, e usando websocket. Utilizza i pacchetti predefiniti predefiniti di meteor.

Potrebbe essere molto più piccolo. Inoltre è persistente tramite il mongo incluso (non è una buona cosa).

Uno screenshot funzionante:

inserisci qui la descrizione dell'immagine

Per eseguire, installare meteor.

Linux:

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

Windows: win.meteor.com

Clona il mio repository ed esegui meteor:

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

punta il tuo browser su localhost: 3000

chat.js: 703 byte (client / server):

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 byte

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 byte

<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
Benvenuti su codegolf! Quel file chat.htmlsembra avere solo 254 byte. Nota che i browser non sono terribilmente pignoli - non mi preoccupo di chiudere i tag e sicuramente non hai bisogno della barra alla fine dei tag (a meno che il nodo non lo richieda?). Inoltre, uccidi più spazi bianchi! Vedo un paio nel javascript e troppo nel HTML.
stand dal
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.