Hard Code Golf: Tạo một Chatroom


13

Cue Storyline: Đó là đầu thế kỷ 21, và hầu hết mọi thứ đã trở thành quá khứ. Tuy nhiên, bạn và đồng nghiệp chơi golf mã của bạn đang thực hiện nhiệm vụ tái hiện những năm 1990. Là một phần của thử thách này, bạn phải tạo lại một phòng chat tối giản.

Mục tiêu: Để tạo một phòng chat với càng ít byte càng tốt. (Các) chương trình mà bạn viết sẽ hoạt động như một máy chủ đơn giản, phục vụ trang web, cho phép người dùng đăng văn bản lên màn hình.

Mục tiêu thực tế: Để thực sự lưu trữ một phòng chat làm việc từ máy tính của riêng bạn. Bạn không cần phải làm điều này, nhưng nó sẽ vui hơn rất nhiều theo cách này.

Yêu cầu:

  • Người dùng có thể cung cấp cho mình tên người dùng kéo dài cho phiên
  • Người dùng sẽ có thể liên tục nhập và gửi văn bản, sẽ được hiển thị cho người dùng khác
  • Mỗi người dùng sẽ có thể xem văn bản được gửi bởi tất cả người dùng, cùng với tên người dùng của người gửi và thông tin sẽ được hiển thị theo thứ tự thời gian
  • Trang này cũng sẽ hiển thị số người trực tuyến và danh sách tên người dùng của họ
  • Phòng chat của bạn nên được truy cập bởi bất kỳ ai trên internet, những người biết tìm nó ở đâu (chẳng hạn như biết địa chỉ IP).
  • Nó nên hoạt động trong các trình duyệt web hiện đại.

Tất cả những thứ khác là tùy thuộc vào bạn!

Đệ trình:

  • Nên bao gồm mã nguồn hoặc liên kết đến mã nguồn
  • Nên bao gồm ảnh chụp màn hình của phòng chat chức năng
  • Phải bao gồm tổng kích thước, tính bằng byte, của tất cả các chương trình / tệp mà bạn đã viết được yêu cầu để làm cho nó hoạt động.

Thử thách này đã ở trong hộp cát được một thời gian rồi, vì vậy hy vọng tất cả các nút thắt đã được giải quyết.


1
nó có được phép không nếu chúng ta buộc các chatter phải gõ từng câu trả lời của họ trong vòng chín giây?
John Dvorak

Tôi nghĩ rằng 9 giây có lẽ là quá ngắn. Một cái gì đó như 99 giây có thể có thể làm việc, mặc dù. Tôi không bao giờ nghĩ đến việc đặt giới hạn thời gian cho các cuộc tán gẫu.
PhiNotPi

định nghĩa "trực tuyến". Chúng tôi có cần đăng lại trước khi dỡ tải không, thời gian chờ 5s sẽ đủ, hoặc chúng tôi thậm chí có được phép yêu cầu mọi người không bao giờ đăng xuất không?
John Dvorak

chúng tôi có được phép cho phép tiêm HTML và các nội dung khác có thể phá vỡ phòng trò chuyện không (miễn là chúng tôi không làm tổn thương máy tính của chính mình)?
John Dvorak

Trên thực tế, bạn có thể làm rõ "nhập từng phản hồi của họ trong vòng chín giây không?" Theo "trực tuyến", tôi có nghĩa là một danh sách những người hiện đang xem phòng chat, chẳng hạn như mở phòng chat trong cửa sổ trình duyệt. Một thời gian chờ sẽ tốt.
PhiNotPi

Câu trả lời:


18

PHP + JQuery + HTML + CSS, 1535 byte

Đây là một đệ trình nghiêng nhiều hơn về những gì OP coi là "mục tiêu thực tế". Đó là, một máy chủ trò chuyện đầy đủ chức năng, có thể được lưu trữ trên bất kỳ máy chủ web nào ở bất cứ đâu.

Chức năng bao gồm:

  • Thông báo khi người dùng vào hoặc ra khỏi phòng chat.
  • Thông báo khi người dùng thay đổi bí danh của họ.
  • Thăm dò thời gian thực cho các tin nhắn mới, mà không tạo ra lưu lượng máy chủ dư thừa hoặc tải máy chủ.
  • Bố cục và khả năng sử dụng rất giống với các ứng dụng trò chuyện hiện có, chẳng hạn như X-Chat.

Để trở thành một phiên, hãy nhập bí danh vào ô thích hợp và nhấn Tabhoặc Enterđể gửi. Nếu bí danh đã được sử dụng, bạn sẽ được thông báo. Gửi tin nhắn cũng được thực hiện thông qua Enter.

Để thuận tiện cho bạn, có thể tìm thấy kho lưu trữ của tất cả các tệp tại đây: chat.zip (chọn Tải xuống từ menu Tệp). Để cài đặt, giải nén vào thư mục web trên bất kỳ máy chủ nào chạy PHP 5.4 trở lên.

Hãy cẩn thận:

  • IE 8 hoặc thấp hơn sẽ quay thành một vòng lặp vô hạn trong khi bỏ phiếu, vì một số lý do mà nhân loại không biết, tất cả các yêu cầu Ajax được lưu trữ theo mặc định. Nó cũng ngăn bạn gửi cùng một tin nhắn hai lần và cập nhật danh sách người dùng đúng cách. Điều này có thể được khắc phục bằng cách thêm cache:falsevào mọi yêu cầu Ajax.
  • Trong tất cả các phiên bản IE, tin nhắn sẽ không được gửi bằng cách nhấn Enter, vì changesự kiện không được kích hoạt (tuy nhiên, nhấn Tab, không hoạt động). Điều này có thể được khắc phục bằng cách thêm một onkeypresstrình xử lý, kiểm tra xem khóa có phải là Enter không, và sau đó gọi $(v).blur().focus().

Nói tóm lại, IE không được hỗ trợ.


Khách hàng

Định vị các yếu tố có thể mạnh hơn một chút, nhưng nó sẽ trông ổn với kích thước cửa sổ tối thiểu khoảng ~ 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})})

Người phục vụ

Tôi xin lỗi vì máy chủ bị chia thành nhiều khối nhỏ. Cách khác là sử dụng một giao thức thông báo đầy đủ (thông qua mã hóa / giải mã JSON) hoặc có một giao thức lớn if ... elseif ...theo đó có các biến bài đăng nào. Tạo các tập lệnh riêng biệt, một yêu cầu chỉ từ một tập lệnh bạn cần ngắn hơn rất nhiều và có lẽ đơn giản hơn cả hai.

o.php (119 byte) O bút làm kết nối đến 'cơ sở dữ liệu'

<?$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 thay đổi thành 'cơ sở dữ liệu'

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

p.php (151 byte) P olls cho tin nhắn mới

<?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 kết thúc một tin nhắn đến máy chủ

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

u.php (222 byte) Đăng ký U ser hoặc thay đổi bí danh

<?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) Lấy danh sách người dùng n ames

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

l.php (98 byte) Người dùng có l eft (đóng trình duyệt của họ)

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

Tôi nghĩ bạn có thể làm onchange=umà không cần dấu ngoặc đơn. Tuy nhiên, bạn sẽ không có được một bối cảnh nhất quán, nhưng dù sao bạn cũng không cần đến nó.
John Dvorak

Bạn có thể làm cho hướng dẫn chi tiết hơn một chút? Tôi muốn thiết lập tính năng này trên máy Mac.
haykam

@Peanut Tôi đã gõ một số hướng dẫn: codepad.org/UKGwb4g2 . Tôi đang làm việc mù, nhưng điều này có thể sẽ làm việc.
primo

13

Con trăn, 230

Điều này là khá tối thiểu, nhưng nó dường như là tùy thuộc vào spec. Người dùng được tính là "xem trang" nếu họ đã trò chuyện trong 99 giây qua.

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)

Điều này sử dụng một trong những thủ thuật rất yêu thích của tôi trong python: các giá trị mặc định chỉ là tham chiếu đến bất cứ thứ gì bạn truyền vào. Nếu đó là một đối tượng có thể thay đổi, nó sẽ xuất hiện trong chuyến đi.

Một cách khác tôi không được sử dụng thường xuyên - cà ri!

Chạy máy chủ:

Chạy tập lệnh trò chuyện từ python (ví dụ python chat.py:) và sau đó trỏ trình duyệt của bạn vào http://localhost:8080để xem một cái gì đó như

ảnh chụp màn hình

Con trăn

Điều này là thực sự tốt đẹp để sử dụng. Đây là golf, vì vậy tôi coi đây là một giải pháp ít thỏa đáng. Bây giờ, tôi lạm dụng iframe và một hình thức với keyhandling ... và meta refresh để thăm dò ý kiến ​​cho nội dung mới.

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

phiên bản 2


2
Tôi nghi ngờ tôi có thể trỏ trình duyệt của mình vào http://localhost:8080/c và truy cập máy chủ HTTP của bạn
John Dvorak

1
@JanDvorak Đó là lý do tại sao tôi không tạo liên kết đó.
gian hàng

1
Đối với những người đã có dịch vụ chạy trên cổng 8080, bạn có thể trả trước những điều sau để sử dụng một cổng khác:S.config.update({'server.socket_port':8090})
primo

Việc cập nhật cửa sổ trò chuyện sẽ khó khăn như thế nào khi bất kỳ ai gửi tin nhắn mới, và không chỉ người dùng? (Ở dạng hiện tại, để kiểm tra xem có tin nhắn mới nào không, bạn cần gửi một tin nhắn trống trước khi cửa sổ của bạn được cập nhật.)
primo

1
@primo Đúng rồi! Đó là cách bạn kiểm tra xem mọi người đã nói gì chưa. Vấn đề được cho là tái hiện những năm 90. Và sau đó, hy vọng người dùng của bạn chấp nhận giao diện được đề xuất bởi mã đơn giản nhất vẫn rất tuyệt. HP đã cho chúng tôi RPN, và chúng tôi thích nó . Suy nghĩ như một 201 * -er giúp bạn có 1280 ký tự phình to.
gian hàng

5

Sao băng: 575 ký tự

Tôi đã có rất nhiều niềm vui với cái này! Ứng dụng này có tại http://cgchat.meteor.com/ .

chat.html: 171 ký tự

<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 ký tự

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

client / client.js: 359 ký tự

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

Liên kết bây giờ đã chết.
lập trình

5

Nút javode / sao băng + html + css + websocket: 1.105 byte

Đây là một cách sử dụng node.js / sao băng . Rõ ràng được viết bằng js, thời gian thực và sử dụng websockets. Sử dụng các gói tích hợp mặc định của sao băng.

Nó có thể nhỏ hơn rất nhiều. Ngoài ra, nó vẫn tồn tại bằng cách sử dụng mongo đi kèm (không phải đó là một điều tốt).

Ảnh chụp màn hình làm việc:

nhập mô tả hình ảnh ở đây

Để thực thi, cài đặt sao băng.

Linux:

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

Windows: win.meteor.com

Nhân bản repo của tôi và thực hiện sao băng:

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

trỏ trình duyệt của bạn tới localhost: 3000

chat.js: 703 byte (máy khách / máy chủ):

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
Chào mừng bạn đến với codegolf! Tập tin đó chat.htmldường như chỉ có 254 byte. Lưu ý rằng các trình duyệt không quá cầu kỳ - Tôi không bận tâm về việc đóng thẻ và bạn chắc chắn không cần dấu gạch chéo ở cuối thẻ (trừ khi nút yêu cầu?). Ngoài ra, giết thêm khoảng trắng! Tôi thấy một vài trong javascript, và quá nhiều trong html.
gian hàng
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.