Hard Code Golf: Sohbet Odası Oluşturun


14

Cue Storyline: 21. yüzyılın başlarıdır ve çoğu şey geçmişte kaldı. Bununla birlikte, siz ve kod-golf arkadaşlarınız 1990'ları yeniden canlandırma arayışındasınız. Bu zorluğun bir parçası olarak, minimalist bir sohbet odası oluşturmalısınız.

Amaç: Mümkün olduğunca az baytlık bir sohbet odası oluşturmak. Yazdığınız programlar, kullanıcıların ekrana metin göndermesini sağlayan bir web sayfası sunan basit bir sunucu olarak işlev görecektir.

Asıl Hedef: Kendi bilgisayarınızdan çalışan bir sohbet odasına ev sahipliği yapmak. Bunu yapmak zorunda değilsiniz, ama bu şekilde çok daha eğlenceli.

Gereksinimler:

  • Kullanıcılar oturum için kalıcı bir kullanıcı adı verebilmelidir.
  • Kullanıcılar, diğer kullanıcılara gösterilecek olan metni tekrar tekrar yazabilmeli ve gönderebilmelidir.
  • Her kullanıcı, gönderenlerin kullanıcı adlarıyla birlikte tüm kullanıcılar tarafından gönderilen metni görebilmeli ve bilgiler kronolojik sırada görüntülenmelidir
  • Sayfa ayrıca çevrimiçi kişi sayısını ve kullanıcı adlarının bir listesini görüntülemelidir
  • Sohbet odasına internette nerede bulacağını bilen herkes erişebilmelidir (IP adresini bilmek gibi).
  • Modern web tarayıcılarında çalışmalıdır.

Diğer her şey size kalmış!

gönderimler:

  • Kaynak kodunu veya kaynak koduna bir bağlantı içermelidir
  • İşlevsel sohbet odasının ekran görüntülerini içermelidir
  • Çalıştırmak için yazdığınız tüm programların / dosyaların bayt cinsinden toplam boyutunu içermelidir.

Bu zorluk bir süredir sandbox'ta, bu yüzden umarım tüm karışıklıklar çözüldü.


1
sohbetleri dokuz saniye içinde yanıtlarının her birini yazmaya zorlarsak izin verilebilir mi?
John Dvorak

Bence 9 saniye muhtemelen çok kısa. Yine de 99 saniye gibi bir şey işe yarayabilir. Sohbet edenlere zaman sınırı koymayı hiç düşünmemiştim.
PhiNotPi

"çevrimiçi" tanımlayın. Boşaltmadan önce tekrar göndermemiz gerekiyor mu, 5 saniyelik zaman aşımı yeterli mi, yoksa insanların asla çıkış yapmadığını iddia etmemize bile izin var mı?
John Dvorak

HTML odasına ve sohbet odasını kırabilecek diğer şeylere izin verebiliriz (kendi bilgisayarımıza zarar vermediğimiz sürece)?
John Dvorak

Aslında, "yanıtlarının her birini dokuz saniye içinde yazabilir misiniz?" "Çevrimiçi" derken, sohbet odasını bir tarayıcı penceresinde açmak gibi, şu anda sohbet odasını görüntüleyen kişilerin bir listesini kastediyorum. Zaman aşımı süresi iyi olacaktır.
PhiNotPi

Yanıtlar:


18

PHP + JQuery + HTML + CSS, 1535 bayt

Bu, OP'nin 'gerçek hedef' olarak gördüğü şeye daha fazla eğilen bir sunumdur. Yani, herhangi bir web sunucusunda herhangi bir yerde barındırılabilecek tamamen işlevsel bir sohbet sunucusu.

İşlevsellik şunları içerir:

  • Kullanıcılar sohbet odasına girdiğinde veya odadan çıktığında bildirim.
  • Kullanıcılar takma adlarını değiştirdiğinde bildirim.
  • Aşırı sunucu trafiği veya sunucu yükü oluşturmadan yeni iletiler için gerçek zamanlı yoklama.
  • Düzen ve kullanılabilirlik, X-Chat gibi mevcut sohbet istemcilerine çok benziyor.

Oturum olmak için uygun kutuya bir takma ad girin ve göndermek için Tabveya tuşuna basın Enter. Takma ad zaten kullanılıyorsa, size bildirilir. Mesaj gönderme de yoluyla yapılır Enter.

Size kolaylık sağlamak için, tüm dosyaların bir arşivini burada bulabilirsiniz: chat.zip (Dosya menüsünden İndir'i seçin). Yüklemek için PHP 5.4 veya daha üst sürümü çalıştıran herhangi bir sunucudaki bir web dizinini paketinden çıkarın.

Uyarılar:

  • IE 8 veya daha düşük bir değer yoklama sırasında sonsuz bir döngüye dönüşür, çünkü insanlık tarafından bilinmeyen bir nedenden dolayı, tüm Ajax istekleri varsayılan olarak önbelleğe alınır. Aynı mesajı iki kez göndermenizi ve kullanıcı listesini düzgün bir şekilde güncellemenizi de önler. Bu, cache:falseher Ajax isteğine eklenerek düzeltilebilir .
  • IE'nin tüm sürümlerinde, changeolay tetiklenmediği için Enter tuşuna basılarak mesaj gönderilmez (ancak Tab tuşuna basıldığında çalışır). Bu, bir onkeypressişleyici ekleyerek , anahtarın Enter olup olmadığını kontrol edip arayarak düzeltilebilir $(v).blur().focus().

Kısacası, IE desteklenmemektedir.


müşteri

Elemanların konumlandırılması biraz daha sağlam olabilir, ancak yaklaşık ~ 800x600 minimum pencere boyutuyla iyi görünmelidir.

chat.htm (190 bayt)

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

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

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

Sunucu

Sunucu çok küçük parçalar halinde ayrılmış olması için özür dilerim. Alternatif, yeterli bir mesaj protokolü (JSON kodlama / kod çözme yoluyla) kullanmak veya if ... elseif ...hangi post değişkenlerinin mevcut olduğuna göre büyük bir büyüklüğe sahip olmaktır. Ayrı komut dosyaları oluşturmak, ihtiyacınız olandan talep etmek çok daha kısa ve belki de her ikisinden daha basittir.

o.php (119 bayt) O 'veritabanındaki bağlantı olarak kalem

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

c.php (57 bayt) ommits 'veritabanındaki değişir

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

p.php (151 bayt) p yeni mesajlar için 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 bayt) S bir iletiyi sunucuya sonlandırır

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

u.php (222 bayt) , U ser kayıt veya takma değişikliği

<?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 bayt), kullanıcının listesini alır n Ames

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

l.php (98 bayt) Kullanıcı sahiptir l EFT (kapalı tarayıcı)

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

Bence onchange=uparantez olmadan yapabilirsiniz . Bununla birlikte, tutarlı bir bağlam elde edemezsiniz, ancak yine de buna ihtiyacınız yoktur.
John Dvorak

Eğiticiyi biraz daha ayrıntılı hale getirebilir misiniz? Bunu Mac'te ayarlamak istiyorum.
haykam

@Peanut Bazı talimatları yazdım : codepad.org/UKGwb4g2 . Kör çalışıyorum, ama muhtemelen işe yarayacak.
primo

14

Python, 230

Bu oldukça az, ama spec kadar görünüyor. Kullanıcılar, son 99 saniyede sohbet ettiyse "sayfayı görüntüleme" olarak sayılır.

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)

Bu, python'daki en sevdiğim hilelerden birini kullanıyor: varsayılan değerler sadece geçtiğiniz her şeye referanslar. Değişebilir bir nesne ise, sadece sürüş için geliyor.

Başka sık kullanamıyorum - köriler!

Sunucuyu Çalıştırma:

Sohbet komut dosyasını python'dan çalıştırın (örneğin, python chat.py) ve ardından tarayıcınızı şuna http://localhost:8080yönlendirin:

ekran görüntüsü

Python, 442

Bu aslında kullanmak güzel. Bu golf, bu yüzden bunu daha az tatmin edici bir çözüm olarak görüyorum. Şimdi, iframe'i ve anahtar işleme içeren bir formu ve yeni içerik için anket oluşturmak üzere meta yenilemeyi kötüye kullanıyorum.

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

versiyon 2


2
Tarayıcımı gösterebileceğimden http://localhost:8080/c ve HTTP sunucunuza erişebileceğimden şüphe ediyorum
John Dvorak

1
@JanDvorak Bu yüzden bunu bir bağlantı yapmadım.
boothby

1
Zaten bağlantı noktasında çalışan bir hizmeti olanlar 8080için, farklı bir bağlantı noktası kullanmak için aşağıdakileri tercih edebilirsiniz:S.config.update({'server.socket_port':8090})
primo

Ne zaman ne kadar zor sohbet penceresi güncellemek olacaktır herkes sadece kullanıcıyı yeni bir ileti gönderir ve olmasın? (Mevcut formunda, yeni mesaj olup olmadığını kontrol etmek için, pencereniz güncellenmeden önce boş bir mesaj göndermeniz gerekir.)
primo

1
@primo Doğru! İnsanların bir şey söylediğini görmek için böyle kontrol edersiniz. Sorun 90'ları yeniden canlandırdığını söyledi. Ve o zamanlar, kullanıcılarınızın en basit kod tarafından önerilen arayüzü kabul etmelerini beklemek hala harikaydı. HP bize RPN verdi ve biz de beğendik . 201 * -er gibi düşünmek size 1280 karakter şişkinlik kazandırır.
boothby

5

Meteor: 575 karakter

Bununla çok eğlendim! Uygulama http://cgchat.meteor.com/ adresinde canlıdır .

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

Bağlantı artık öldü.
programmer5000

5

Düğüm / Meteor javascript + html + css + websocket: 1.105 bayt

İşte node.js / meteor kullanan biri . Açıkçası js, gerçek zamanlı ve websockets kullanarak yazılmıştır. Meteor'un varsayılan yerleşik paketlerini kullanır.

Çok daha küçük olabilir. Ayrıca dahil olan mongo ile kalıcı (bu iyi bir şey değil).

Çalışan bir ekran görüntüsü:

resim açıklamasını buraya girin

Yürütmek için meteor'ı yükleyin.

Linux:

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

Windows: win.meteor.com

Reporumu klonlayın ve meteor çalıştırın:

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

tarayıcınızı localhost'a yönlendirin: 3000

chat.js: 703 bayt (istemci / sunucu):

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 bayt

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 bayt

<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'a Hoşgeldiniz! Bu dosyada chat.htmlsadece 254 bayt var. Tarayıcıların çok seçici olmadığını unutmayın - Etiketleri kapatmak için zahmet etmiyorum ve etiketlerin sonunda kesinlikle eğik çizgiye ihtiyacınız yok (düğüm gerektirmedikçe?). Ayrıca, daha fazla boşluk öldürün! Javascript'te bir çift görüyorum ve html'de çok fazla.
boothby
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.