ハードコードゴルフ:チャットルームを作成する


13

Cue Storyline: 21世紀初頭であり、ほとんどのものは過去のものになっています。しかし、あなたとあなたの仲間のコードゴルフ愛好家は、1990年代を再現しようとしています。この課題の一部として、最小限のチャットルームを作り直す必要があります。

目標: できるだけ少ないバイト数でチャットルームを作成する。作成するプログラムは、ユーザーが画面にテキストを投稿できるWebページを提供する単純なサーバーとして機能します。

実際の目標: 自分のコンピューターから実際に動作するチャットルームをホストすること。これを行う必要はありませんが、この方法の方がずっと楽しいです。

要件:

  • ユーザーは、セッションが続くユーザー名を自分で入力できる必要があります。
  • ユーザーは、他のユーザーに表示されるテキストを繰り返し入力および送信できる必要があります。
  • 各ユーザーは、すべてのユーザーによって送信されたテキストと、送信者のユーザー名を表示でき、情報は時系列で表示される必要があります。
  • ページには、オンラインの人数とユーザー名のリストも表示する必要があります
  • チャットルームは、インターネット上のどこからでも見つけられる場所(IPアドレスを知っているなど)にアクセスできる必要があります。
  • 最新のWebブラウザで機能するはずです。

他のすべてはあなた次第です!

提出:

  • ソースコード、またはソースコードへのリンクを含める必要があります
  • 機能的なチャットルームのスクリーンショットを含める必要があります
  • 動作させるために必要なすべてのプログラム/ファイルの合計サイズをバイト単位で含める必要があります。

この課題はサンドボックス内にしばらくの間存在しているため、すべてのねじれが解決されたことを願っています。


1
9秒以内にチャットの各応答を強制的に入力するように強制した場合、許容されますか?
ジョンドボラック

9秒はおそらく短すぎると思います。ただし、99秒のようなものがおそらく動作する可能性があります。おしゃべりに時間制限をかけるなんて考えもしなかった。
PhiNotPi

「オンライン」を定義します。アンロードする前にポストバックする必要がありますか、5秒のタイムアウトで十分ですか、それともユーザーがログオフしないと主張することさえできますか?
ジョンドヴォルザーク

チャットルームを壊す可能性のあるHTMLインジェクションやその他のものを許可できますか(自分のコンピューターを傷つけない限り)。
ジョン・ドヴォルザーク

実際、「9秒以内に各回答を入力してください」と明確にできますか?「オンライン」とは、ブラウザウィンドウでチャットルームを開くなど、チャットルームを現在表示しているユーザーのリストを意味します。タイムアウトは問題ありません。
PhiNotPi

回答:


18

PHP + JQuery + HTML + CSS、1535バイト

これは、OPが「実際の目標」とみなしたものにより傾いた提出です。つまり、完全に機能するチャットサーバーであり、ほぼすべてのWebサーバーでホストできます。

機能が含まれます:

  • ユーザーがチャットルームに出入りするときの通知。
  • ユーザーがエイリアスを変更したときの通知。
  • 過剰なサーバートラフィックやサーバー負荷を発生させることなく、新しいメッセージをリアルタイムでポーリングします。
  • X-Chatなどの既存のチャットクライアントに非常によく似たレイアウトと使いやすさ。

セッションになるには、適切なボックスにエイリアスを入力し、TabまたはEnterを押して送信します。エイリアスが既に使用されている場合は、通知されます。メッセージの送信もを介して行われますEnter

便宜上、すべてのファイルのアーカイブは、chat.zip([ファイル]メニューから[ダウンロード]を選択)にあります。インストールするには、PHP 5.4以降を実行しているサーバーのWebディレクトリに解凍します。

警告:

  • IE 8以下は、ポーリング中に無限ループにスピンします。これは、何らかの理由で人類に知られておらず、すべてのAjaxリクエストがデフォルトでキャッシュされるためです。また、同じメッセージを2回送信して、ユーザーリストを適切に更新することもできません。これはcache:false、すべてのAjaxリクエストに追加することで修正できます。
  • IEのすべてのバージョンでchangeは、イベントがトリガーされないため、Enterキーを押してもメッセージは送信されません(ただし、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})})

サーバ

サーバーが非常に多くの小さなチャンクに分割されていることをおizeび申し上げます。別の方法としては、適切なメッセージプロトコル(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 'データベース'にommits変更を

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

p.php(151バイト)Pの新しいメッセージのolls

<?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でセットアップしたい。
-haykam

@Peanut codepad.org/UKGwb4g2の指示を入力しました。私は盲目で働いていますが、これはおそらくうまくいくでしょう。
プリモ

13

Python、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で私のお気に入りのトリックの1つを使用します。デフォルト値は、渡されたものへの単なる参照です。それが可変オブジェクトである場合は、そのまま使用できます。

もう1つはよく使用しません-カレー!

サーバーの実行:

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それが、私がそのリンクを作成しなかった理由です。
ブースバイ

1
ポート8080でサービスを既に実行している場合は、次を追加して別のポートを使用できますS.config.update({'server.socket_port':8090})
。– primo

ユーザーだけでなく、誰かが新しいメッセージを送信したときにチャットウィンドウを更新することはどれほど難しいでしょうか?(現在のフォームでは、新しいメッセージがあるかどうかを確認するには、ウィンドウが更新される前に空白のメッセージを送信する必要があります。)
primo

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

リンクは現在無効です。
Programmer5000

5

Node / Meteor javascript + html + css + websocket:1,105バイト

node.js / meteorを使用したものです。明らかにjs、リアルタイムで記述され、websocketを使用しています。meteorのデフォルトの組み込みパッケージを使用します。

それはもっと小さいかもしれません。また、付属のmongoを使用して永続化されます(それは良いことではありません)。

動作中のスクリーンショット:

ここに画像の説明を入力してください

実行するには、meteorをインストールします。

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であまりにも多く見ます。
ブースビー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.