Hard Code Golf: Buat Ruang Obrolan

13

Cue Storyline: Ini adalah awal abad ke-21, dan sebagian besar hal telah menjadi sesuatu dari masa lalu. Namun, Anda dan sesama kode-golf-etawan sedang berupaya menghidupkan kembali tahun 1990-an. Sebagai bagian dari tantangan ini, Anda harus membuat ulang ruang obrolan minimalis.

Tujuan: Untuk membuat ruang obrolan dengan sesedikit mungkin byte. Program yang Anda tulis akan berfungsi sebagai server sederhana, yang melayani halaman web, yang memungkinkan pengguna memposting teks ke layar.

Tujuan Aktual: Untuk benar-benar menyelenggarakan ruang obrolan yang berfungsi dari komputer Anda sendiri. Anda tidak harus melakukan ini, tetapi jauh lebih menyenangkan dengan cara ini.

Persyaratan:

  • Pengguna harus dapat memberikan sendiri nama pengguna yang tahan untuk sesi ini
  • Pengguna harus dapat berulang kali mengetik dan mengirim teks, yang akan ditampilkan kepada pengguna lain
  • Setiap pengguna harus dapat melihat teks yang dikirimkan oleh semua pengguna, bersama dengan nama pengguna pengirim, dan informasi harus ditampilkan dalam urutan kronologis
  • Halaman ini juga harus menampilkan jumlah orang yang online dan daftar nama pengguna mereka
  • Ruang obrolan Anda harus dapat diakses oleh siapa saja di internet yang tahu di mana menemukannya (seperti mengetahui alamat IP).
  • Seharusnya berfungsi di browser web modern.

Semuanya terserah Anda!

Pengajuan:

  • Harus menyertakan kode sumber, atau tautan ke kode sumber
  • Harus menyertakan tangkapan layar ruang obrolan fungsional
  • Harus mencakup ukuran total, dalam byte, dari semua program / file yang Anda tulis yang diperlukan untuk membuatnya berfungsi.

Tantangan ini telah berada di kotak pasir untuk sementara waktu sekarang, jadi semoga semua ketegaran telah berhasil.

PhiNotPi
sumber
1
apakah akan diizinkan jika kita memaksa chatters untuk mengetik setiap tanggapan mereka dalam waktu sembilan detik?
John Dvorak
Saya pikir 9 detik mungkin terlalu pendek. Sekitar 99 detik mungkin bisa bekerja. Saya tidak pernah berpikir untuk membatasi waktu mengobrol.
PhiNotPi
tentukan "online". Apakah kita perlu memposting kembali sebelum membongkar, batas waktu 5s sudah cukup, atau kita bahkan diizinkan untuk mengklaim orang tidak pernah logout?
John Dvorak
apakah kita diizinkan untuk mengizinkan injeksi HTML dan hal-hal lain yang dapat merusak ruang obrolan (selama kita tidak melukai komputer kita sendiri)?
John Dvorak
Sebenarnya, dapatkah Anda mengklarifikasi "ketikkan setiap respons mereka dalam sembilan detik?" Dengan "online," maksud saya adalah daftar orang-orang yang saat ini melihat chatroom, seperti membuka chatroom di jendela browser. Batas waktu akan baik-baik saja.
PhiNotPi

Jawaban:

18

PHP + JQuery + HTML + CSS, 1535 byte

Ini adalah submission yang lebih condong ke apa yang dianggap OP sebagai 'tujuan aktual'. Yaitu, server obrolan yang berfungsi penuh, yang dapat di-host di hampir semua server web di mana saja.

Fungsionalitas meliputi:

  • Pemberitahuan saat pengguna masuk atau keluar dari ruang obrolan.
  • Pemberitahuan saat pengguna mengubah alias mereka.
  • Polling waktu nyata untuk pesan baru, tanpa menghasilkan lalu lintas server berlebih, atau beban server.
  • Tata letak dan kegunaan sangat menyerupai klien obrolan yang ada, seperti X-Chat.

Untuk menjadi sesi, masukkan alias di kotak yang sesuai, dan tekan Tabatau Enteruntuk mengirim. Jika alias sudah digunakan, Anda akan diberi tahu. Mengirim pesan juga dilakukan melalui Enter.

Untuk kenyamanan Anda, arsip semua file dapat ditemukan di sini: chat.zip (pilih Unduh dari menu File). Untuk menginstal, buka paket ke direktori web di server mana saja yang menjalankan PHP 5.4 atau lebih tinggi.

Peringatan:

  • IE 8 atau lebih rendah akan berputar menjadi loop tak terbatas saat pemungutan suara, karena untuk beberapa alasan yang tidak diketahui umat manusia, semua permintaan Ajax di-cache secara default. Ini juga mencegah Anda mengirim pesan yang sama dua kali, dan memperbarui daftar pengguna dengan benar. Ini bisa diperbaiki dengan menambahkan cache:falseke setiap permintaan Ajax.
  • Di semua versi IE, pesan tidak akan dikirim dengan menekan Enter, karena changeacara tidak dipicu (menekan Tab, bagaimanapun, tidak berfungsi). Ini bisa diperbaiki dengan menambahkan onkeypresspawang, memeriksa apakah kuncinya adalah Enter, dan kemudian memanggil $(v).blur().focus().

Singkatnya, IE tidak didukung.


Klien

Posisi elemen bisa sedikit lebih kuat, tetapi harus terlihat baik-baik saja dengan ukuran jendela minimum sekitar ~ 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 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

Saya minta maaf untuk server yang dipecah menjadi begitu banyak potongan kecil Alternatifnya adalah dengan menggunakan protokol pesan yang memadai (melalui JSON encode / decode), atau memiliki besar if ... elseif ...sesuai dengan variabel posting yang hadir. Membuat skrip terpisah, meminta hanya dari yang Anda butuhkan jauh lebih pendek, dan mungkin lebih sederhana dari keduanya.

o.php (119 bytes) O pens sebagai koneksi ke 'database'

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

c.php (57 bytes) C ommits perubahan ke 'database'

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

p.php (151 bytes) P olls untuk pesan baru

<?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 mengakhiri pesan ke server

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

u.php (222 bytes) U pendaftaran ser atau perubahan 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) Mengambil daftar pengguna n ames

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

l.php (98 byte) Pengguna memiliki l eft (menutup peramban mereka)

<?include('o.php');$m[]=[$t,"<i><b>$l</b> has left the chat.</i>"];
unset($u[$l]);include('c.php');
primo
sumber
Saya pikir Anda bisa melakukannya onchange=utanpa tanda kurung. Anda tidak akan mendapatkan konteks yang konsisten, tetapi Anda tidak membutuhkannya.
John Dvorak
Bisakah Anda membuat tutorial sedikit lebih detail? Saya ingin mengatur ini di Mac.
haykam
@Peanut Saya mengetik beberapa instruksi: codepad.org/UKGwb4g2 . Saya bekerja buta, tetapi ini mungkin akan berhasil.
Primo
13

Python, 230

Ini cukup minim, tetapi tampaknya sesuai dengan spesifikasi. Pengguna dihitung sebagai "melihat halaman" jika mereka mengobrol dalam 99 detik terakhir.

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)

Ini menggunakan salah satu trik favorit saya dalam python: nilai default hanyalah referensi untuk apa pun yang Anda lewati. Jika itu adalah objek yang bisa berubah, ia hanya ikut dalam perjalanan.

Lain saya tidak bisa sering digunakan - kari!

Menjalankan Server:

Jalankan skrip obrolan dari python (misalnya, python chat.py) lalu arahkan browser Anda http://localhost:8080untuk melihat sesuatu

tangkapan layar

Python, 442

Yang ini sebenarnya bagus untuk digunakan. Ini golf, jadi saya menganggap ini solusi yang kurang memuaskan. Sekarang, saya menyalahgunakan iframe dan formulir dengan penanganan kunci ... dan meta refresh untuk polling untuk konten baru.

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

versi 2

stan
sumber
2
Saya ragu saya dapat mengarahkan browser saya http://localhost:8080/c dan mengakses server HTTP Anda
John Dvorak
1
@JanDvorak Itu sebabnya saya tidak membuat tautan.
boothby
1
Bagi mereka yang sudah memiliki layanan yang berjalan pada port 8080, Anda dapat menambahkan berikut ini untuk menggunakan port yang berbeda:S.config.update({'server.socket_port':8090})
primo
Seberapa sulitkah memperbarui jendela obrolan ketika ada orang yang mengirim pesan baru, dan bukan hanya pengguna? (Dalam bentuk saat ini, untuk memeriksa apakah ada pesan baru, Anda perlu mengirim pesan kosong sebelum jendela Anda diperbarui.)
primo
1
@primo Benar! Begitulah cara Anda memeriksa untuk melihat apakah orang mengatakan sesuatu. Masalahnya dikatakan mengaktifkan kembali 90-an. Dan saat itu, mengharapkan pengguna Anda untuk menerima antarmuka yang disarankan oleh kode paling sederhana masih keren. HP memberi kami RPN, dan kami menyukainya . Berpikir seperti 201 * -er memberi Anda 1.280 karakter mengasapi.
stan
5

Meteor: 575 karakter

Saya bersenang-senang dengan yang satu ini! Aplikasi ini tayang langsung di http://cgchat.meteor.com/ .

chat.html: 171 karakter

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

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

client / client.js: 359 karakter

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
sumber
Tautan sekarang mati.
programmer5000
5

Node / Meteor javascript + html + css + websocket: 1,105 byte

Berikut ini salah satu yang menggunakan node.js / meteor . Jelas ditulis dalam js, realtime, dan menggunakan soket web. Menggunakan paket bawaan bawaan meteor.

Bisa jadi jauh lebih kecil. Juga gigih melalui mongo yang disertakan (bukan itu hal yang baik).

Tangkapan layar yang berfungsi:

masukkan deskripsi gambar di sini

Untuk mengeksekusi, instal meteor.

Linux:

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

Windows: win.meteor.com

Kloning repo saya dan jalankan meteor:

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

arahkan browser Anda ke localhost: 3000

chat.js: 703 bytes (klien / 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 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>
beeradg
sumber
1
Selamat datang di codegolf! File itu chat.htmltampaknya hanya memiliki 254 byte. Perhatikan bahwa browser tidak terlalu pilih-pilih - Saya tidak repot-repot untuk menutup tag, dan Anda pasti tidak memerlukan garis miring di akhir tag (kecuali jika simpul mengharuskannya?). Juga, bunuh lebih banyak ruang putih! Saya melihat pasangan di javascript, dan terlalu banyak di html.
booth