Hard Code Golf: Erstelle einen Chatraum

13

Cue-Handlung: Es ist das frühe 21. Jahrhundert, und die meisten Dinge gehören der Vergangenheit an. Sie und Ihre Mitstreiter sind jedoch auf der Suche nach einer Nachstellung der neunziger Jahre. Als Teil dieser Herausforderung müssen Sie einen minimalistischen Chatroom neu erstellen.

Das Ziel: Einen Chatroom mit möglichst wenigen Bytes erstellen. Das Programm, das Sie schreiben, fungiert als einfacher Server, der eine Webseite bereitstellt, auf der Benutzer Text auf dem Bildschirm veröffentlichen können.

Das eigentliche Ziel: Einen funktionierenden Chatroom von Ihrem eigenen Computer aus hosten. Sie müssen das nicht tun, aber auf diese Weise macht es viel mehr Spaß.

Bedarf:

  • Benutzer sollten in der Lage sein, sich einen Benutzernamen zu geben, der für die Sitzung gültig ist
  • Benutzer sollten in der Lage sein, wiederholt Text einzugeben und zu übermitteln, der anderen Benutzern angezeigt wird
  • Jeder Benutzer sollte in der Lage sein, den von allen Benutzern eingereichten Text zusammen mit den Benutzernamen der Absender zu sehen, und die Informationen sollten in chronologischer Reihenfolge angezeigt werden
  • Die Seite sollte auch die Anzahl der Online-Benutzer und eine Liste ihrer Benutzernamen anzeigen
  • Ihr Chatroom sollte für jeden im Internet zugänglich sein, der weiß, wo er zu finden ist (z. B. die IP-Adresse zu kennen).
  • Es sollte in modernen Webbrowsern funktionieren.

Alles andere liegt bei Ihnen!

Einsendungen:

  • Sollte den Quellcode oder einen Link zum Quellcode enthalten
  • Sollte Screenshots des funktionierenden Chatrooms enthalten
  • Sollte die Gesamtgröße aller von Ihnen geschriebenen Programme / Dateien in Byte enthalten, die erforderlich sind, damit sie funktionieren.

Diese Herausforderung ist jetzt schon eine Weile in der Sandkiste, also sind hoffentlich alle Probleme gelöst.

PhiNotPi
quelle
1
Wäre es zulässig, wenn wir die Chatter zwingen würden, jede ihrer Antworten innerhalb von neun Sekunden einzugeben?
John Dvorak
Ich denke, dass 9 Sekunden wahrscheinlich zu kurz sind. Etwas wie 99 Sekunden könnten jedoch wahrscheinlich funktionieren. Ich hätte nie daran gedacht, die Chatter zeitlich zu begrenzen.
PhiNotPi
definieren Sie "online". Müssen wir vor dem Entladen wieder posten, 5s Timeout wird ausreichen, oder dürfen wir sogar behaupten, dass sich Leute niemals abmelden?
John Dvorak
Dürfen wir HTML-Injection und andere Dinge zulassen, die den Chatraum beschädigen könnten (solange wir unseren eigenen Computer nicht verletzen)?
John Dvorak
Können Sie tatsächlich klarstellen, "ob Sie jede ihrer Antworten innerhalb von neun Sekunden eingeben"? Mit "online" meine ich eine Liste von Personen, die derzeit den Chatroom anzeigen, z. B. wenn der Chatroom in einem Browserfenster geöffnet ist. Eine Auszeit ist in Ordnung.
PhiNotPi

Antworten:

18

PHP + JQuery + HTML + CSS, 1535 Byte

Dies ist ein Beitrag, der eher dem entspricht, was das OP als "das eigentliche Ziel" ansieht. Dies ist ein voll funktionsfähiger Chat-Server, der auf nahezu jedem Webserver gehostet werden kann.

Die Funktionalität umfasst:

  • Benachrichtigungen, wenn Benutzer den Chatraum betreten oder verlassen.
  • Benachrichtigungen, wenn Benutzer ihren Alias ​​ändern.
  • Echtzeit-Abfrage nach neuen Nachrichten, ohne übermäßigen Serververkehr oder Serverauslastung zu generieren.
  • Layout und Benutzerfreundlichkeit ähneln stark vorhandenen Chat-Clients, wie beispielsweise X-Chat.

Um eine Sitzung zu sein, geben Sie einen Alias ​​in das entsprechende Feld ein und drücken Sie Taboder Enter, um zu übermitteln. Wenn der Alias ​​bereits verwendet wird, werden Sie benachrichtigt. Das Senden von Nachrichten erfolgt ebenfalls über Enter.

Ein Archiv aller Dateien finden Sie hier: chat.zip (wählen Sie "Download" im Menü "Datei"). Entpacken Sie zum Installieren in ein Webverzeichnis auf einem Server, auf dem PHP 5.4 oder höher ausgeführt wird.

Vorsichtsmaßnahmen:

  • IE 8 oder niedriger wird beim Abrufen in eine Endlosschleife umgewandelt, da aus irgendeinem Grund, den die Menschheit nicht kennt, alle Ajax-Anforderungen standardmäßig zwischengespeichert werden. Außerdem wird verhindert, dass Sie dieselbe Nachricht zweimal senden und die Benutzerliste ordnungsgemäß aktualisieren. Dies könnte durch Hinzufügen cache:falsezu jeder Ajax-Anfrage behoben werden .
  • In allen IE-Versionen werden Nachrichten nicht durch Drücken der Eingabetaste gesendet, da das changeEreignis nicht ausgelöst wird (das Drücken der Tabulatortaste funktioniert jedoch). Dies kann behoben werden, indem Sie einen onkeypressHandler hinzufügen , prüfen, ob der Schlüssel die Eingabetaste ist, und dann anrufen $(v).blur().focus().

Kurz gesagt, IE wird nicht unterstützt.


Klient

Die Positionierung von Elementen könnte etwas robuster sein, sollte aber mit einer minimalen Fenstergröße von ca. 800x600 gut aussehen.

chat.htm (190 Bytes)

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

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

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

Ich entschuldige mich dafür, dass der Server in so viele kleine Brocken aufgeteilt wurde. Die Alternative wäre die Verwendung eines geeigneten Nachrichtenprotokolls (über JSON-Codierung / -Decodierung) oder die Verwendung eines großen Protokolls, if ... elseif ...nach dem Post-Variablen vorhanden sind. Das Erstellen separater Skripte, eine einfache Anforderung von dem, den Sie benötigen, ist viel kürzer und möglicherweise einfacher als beide.

o.php (119 bytes) O pens als verbindung zur 'datenbank'

<?$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 ändert sich in den 'Datenbank'

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

p.php (151 bytes) P olls für neue Nachrichten

<?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 bytes) S Beendet eine Nachricht an den Server

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

u.php (222 bytes) U ser Anmeldung oder Alias Änderung

<?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 Bytes) Ruft die Liste der Benutzer n artien

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

l.php (98 bytes) Benutzer hat l eft (Browser geschlossen)

<?include('o.php');$m[]=[$t,"<i><b>$l</b> has left the chat.</i>"];
unset($u[$l]);include('c.php');
primo
quelle
Ich denke, man kann onchange=uohne die Klammern auskommen. Sie werden jedoch keinen konsistenten Kontext erhalten, aber Sie brauchen ihn trotzdem nicht.
John Dvorak
Können Sie das Tutorial etwas detaillierter gestalten? Ich möchte dies auf einem Mac einrichten.
Haykam
@ Erdnuss Ich habe einige Anweisungen eingegeben : codepad.org/UKGwb4g2 . Ich arbeite blind, aber das wird wahrscheinlich funktionieren.
Primo
13

Python, 230

Dies ist ziemlich minimal, aber es scheint den Spezifikationen zu entsprechen. Benutzer werden als "Anzeigen der Seite" gezählt, wenn sie in den letzten 99 Sekunden gechattet haben.

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)

Dies verwendet einen meiner beliebtesten Tricks in Python: Standardwerte sind nur Verweise auf alles, was Sie übergeben haben. Wenn es sich um ein veränderbares Objekt handelt, wird es nur für die Fahrt bereitgestellt.

Ein anderes, das ich nicht oft benutze - Currys!

Server ausführen:

Führen Sie den Chat - Skript aus Python (zum Beispiel python chat.py) und dann Ihren Browser darauf an http://localhost:8080so etwas wie zu sehen

Bildschirmfoto

Python, 442

Dieser ist eigentlich schön zu bedienen. Dies ist Golf, daher halte ich dies für eine weniger zufriedenstellende Lösung. Jetzt missbrauche ich einen Iframe und ein Formular mit Schlüsselbehandlung ... und eine Meta-Aktualisierung, um nach neuen Inhalten zu suchen.

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

Version 2

boothby
quelle
2
Ich bezweifle, dass ich mit meinem Browser auf http://localhost:8080/c Ihren HTTP-Server zugreifen kann
John Dvorak
1
@ JanDvorak Deshalb habe ich das nicht zu einem Link gemacht.
Stand
1
Für diejenigen, die bereits einen Dienst auf dem Port haben 8080, können Sie Folgendes voranstellen, um einen anderen Port zu verwenden:S.config.update({'server.socket_port':8090})
primo
Wie schwierig wäre es, das Chatfenster zu aktualisieren, wenn jemand eine neue Nachricht sendet und nicht nur der Benutzer? (Um zu überprüfen, ob neue Nachrichten vorhanden sind, müssen Sie in der aktuellen Form eine leere Nachricht senden, bevor Ihr Fenster aktualisiert wird.)
primo
1
@primo Richtig! So prüfen Sie, ob jemand etwas gesagt hat. Das Problem soll die 90er Jahre nachspielen. Und damals war es noch cool zu erwarten, dass Ihre Benutzer die vom einfachsten Code vorgeschlagene Benutzeroberfläche akzeptieren. HP gab uns RPN, und es hat uns gefallen . Wenn du wie ein 201 * -Roller denkst, bekommst du 1280 aufgedunsene Zeichen.
Stand
5

Meteor: 575 Zeichen

Ich hatte viel Spaß mit diesem! Die Anwendung ist live unter http://cgchat.meteor.com/ verfügbar .

chat.html: 171 zeichen

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

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

client / client.js: 359 Zeichen

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()}
Pieter Bos
quelle
Link ist jetzt tot.
programmer5000
5

Node / Meteor Javascript + HTML + CSS + Websocket: 1.105 Bytes

Hier ist eine mit node.js / meteor . Natürlich in js, Echtzeit und mit Websockets geschrieben. Verwendet die Standardpakete von meteor.

Es könnte viel kleiner sein. Auch durch den enthaltenen Mongo ist es hartnäckig (nicht, dass das eine gute Sache ist).

Ein funktionierender Screenshot:

Bildbeschreibung hier eingeben

Zum Ausführen installieren Sie meteor.

Linux:

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

Windows: win.meteor.com

Klone mein Repo und führe den Meteor aus:

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

Zeigen Sie mit Ihrem Browser auf localhost: 3000

chat.js: 703 Bytes (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 bytes

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 bytes

<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
quelle
1
Willkommen bei Codegolf! Diese Datei chat.htmlscheint nur 254 Bytes zu haben. Beachten Sie, dass Browser nicht sonderlich wählerisch sind - ich möchte Tags nicht schließen, und Sie benötigen definitiv keinen Schrägstrich am Ende von Tags (es sei denn, der Knoten benötigt diesen?). Töte auch mehr Leerzeichen! Ich sehe ein paar im Javascript und viel zu viel im HTML.
Stand