Hard Code Golf: Crie uma sala de chat


13

Cue Storyline: É o início do século 21, e a maioria das coisas se tornou coisa do passado. Você e seus colegas jogadores de código de golfe, no entanto, estão em uma missão para reencenar os anos 90. Como parte desse desafio, você deve recriar uma sala de bate-papo minimalista.

O objetivo: criar uma sala de bate-papo com o mínimo de bytes possível. Os programas que você escreve devem funcionar como um servidor simples, que serve uma página da Web, que permite aos usuários postar texto na tela.

O objetivo real: Realmente hospedar uma sala de chat em funcionamento a partir do seu próprio computador. Você não precisa fazer isso, mas é muito mais divertido assim.

Requisitos:

  • Os usuários devem poder fornecer um nome de usuário que dure pela sessão
  • Os usuários devem poder digitar e enviar repetidamente texto, que será exibido para outros usuários
  • Cada usuário deve poder ver o texto que é enviado por todos os usuários, juntamente com os nomes de usuários dos remetentes, e as informações devem ser exibidas em ordem cronológica
  • A página também deve exibir o número de pessoas on-line e uma lista de seus nomes de usuário
  • Sua sala de bate-papo deve estar acessível a qualquer pessoa na internet que saiba onde encontrá-la (como saber o endereço IP).
  • Ele deve funcionar em navegadores modernos.

Tudo o resto é com você!

Submissões:

  • Deve incluir o código fonte ou um link para o código fonte
  • Deve incluir capturas de tela da sala de chat funcional
  • Deve incluir o tamanho total, em bytes, de todos os programas / arquivos que você escreveu, necessários para fazê-lo funcionar.

Esse desafio está na caixa de areia há um tempo, então, espero que todas as dobras tenham sido resolvidas.


1
seria permitido se forçássemos os participantes a digitar cada uma de suas respostas em nove segundos?
— John Dvorak

Eu acho que 9 segundos provavelmente é muito curto. Algo como 99 segundos provavelmente poderia funcionar, no entanto. Eu nunca pensei em colocar limites de tempo nas conversas.
— PhiNotPi 4/08/13

defina "online". Precisamos postar novamente antes da descarga, o tempo limite de 5s será suficiente ou podemos reivindicar que as pessoas nunca saiam?
— John Dvorak

podemos permitir a injeção de HTML e outras coisas que podem quebrar a sala de bate-papo (desde que não danifiquemos nosso próprio computador)?
— John Dvorak

Na verdade, você pode esclarecer "digite cada uma das respostas em nove segundos?" Por "online", eu significaria uma lista de pessoas que atualmente estão visualizando a sala de bate-papo, como abrir a sala de bate-papo em uma janela do navegador. Um tempo limite será bom.
— PhiNotPi

Respostas:


18

PHP + JQuery + HTML + CSS, 1535 bytes

Esta é uma submissão que se inclina mais para o que o OP considerou como 'o objetivo real'. Ou seja, um servidor de bate-papo totalmente funcional, que pode ser hospedado em praticamente qualquer servidor Web em qualquer lugar.

A funcionalidade inclui:

  • Notificações quando os usuários entram ou saem da sala de bate-papo.
  • Notificações quando os usuários alteram seu alias.
  • Pesquisa em tempo real para novas mensagens, sem gerar excesso de tráfego ou carga no servidor.
  • Layout e usabilidade muito semelhantes aos clientes de bate-papo existentes, como o X-Chat.

Para ser uma sessão, insira um alias na caixa apropriada e pressione Tabou Enterpara enviar. Se o alias já estiver em uso, você será notificado. O envio de mensagens também é feito via Enter.

Para sua conveniência, um arquivo de todos os arquivos pode ser encontrado aqui: chat.zip (escolha Download no menu Arquivo). Para instalar, descompacte em um diretório da web em qualquer servidor executando o PHP 5.4 ou superior.

Ressalvas:

  • O IE 8 ou inferior girará em um loop infinito durante a pesquisa, porque, por algum motivo desconhecido para a humanidade, todas as solicitações do Ajax são armazenadas em cache por padrão. Também impede que você envie a mesma mensagem duas vezes e atualize a lista de usuários corretamente. Isso pode ser corrigido adicionando cache:falsea cada solicitação do Ajax.
  • Em todas as versões do IE, as mensagens não serão enviadas pressionando Enter, porque o changeevento não é acionado (pressionar Tab, no entanto, funciona). Isso poderia ser corrigido adicionando um onkeypressmanipulador, verificando se a chave era Enter e depois chamando $(v).blur().focus().

Em suma, o IE não é suportado.


Cliente

O posicionamento dos elementos pode ser um pouco mais robusto, mas deve ficar bem com um tamanho mínimo de janela de aproximadamente ~ 800x600.

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

Servidor

Peço desculpas pelo servidor estar dividido em tantos pequenos pedaços. A alternativa seria usar um protocolo de mensagem adequado (via JSON codificar / decodificar) ou ter um grande de if ... elseif ...acordo com o qual as variáveis ​​de postagem estão presentes. Criando scripts separados, basta solicitar o que você precisa é muito mais curto e talvez mais simples que os dois.

o.php (119 bytes) O canetas como conexão com o 'banco de dados'

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

c.php (57 bytes) C omite alterações no 'banco de dados'

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

p.php (151 bytes) P olls para novas mensagens

<?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 finaliza uma mensagem para o servidor

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

u.php (222 bytes) L registo Ser ou mudança de 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 bytes) recupera a lista de utilizador n ames

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

l.php (98 bytes) Usuário l eft (fechou o navegador)

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

Eu acho que você pode ficar onchange=usem os parênteses. Você não terá um contexto consistente, no entanto, mas não precisará disso.
— John Dvorak

Você pode tornar o tutorial um pouco mais detalhado? Eu quero configurar isso em um Mac.
— haykam

@ Amendoim, digitei algumas instruções: codepad.org/UKGwb4g2 . Estou trabalhando às cegas, mas isso provavelmente funcionará.
— Primo

13

Python, 230

Isso é mínimo, mas parece estar dentro das especificações. Os usuários são contados como "visualizando a página" se tiverem conversado nos últimos 99 segundos.

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)

Isso usa um dos meus truques favoritos em python: os valores padrão são apenas referências ao que você passou. Se é um objeto mutável, ele apenas aparece.

Outro que eu não uso com frequência - curry!

Executando o servidor:

Execute o script de bate-papo a partir de python (por exemplo python chat.py) e aponte o navegador http://localhost:8080para ver algo como

captura de tela

Python, 442

Este é realmente bom de usar. Isso é golfe, então considero isso uma solução menos satisfatória. Agora, eu abusei de um iframe e de um formulário com manipulação de teclas ... e uma meta atualização para pesquisar novos conteúdos.

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

versão 2


2
Eu duvido que eu posso apontar meu navegador no http://localhost:8080/c e acessar o servidor HTTP
— John Dvorak

1
@JanDvorak Foi por isso que não fiz disso um link.
— usar o seguinte código

1
Para aqueles que já possuem um serviço em execução na porta 8080, você pode acrescentar o seguinte para usar uma porta diferente:S.config.update({'server.socket_port':8090})
— primo

Quão difícil seria atualizar a janela de bate-papo quando alguém envia uma nova mensagem, e não apenas o usuário? (Na sua forma atual, a fim de verificar se existem novas mensagens, você precisa enviar uma mensagem em branco antes de sua janela é atualizada.)
— primo

1
@primo Right! É assim que você verifica se as pessoas disseram alguma coisa. O problema dizia reencenar os anos 90. E naquela época, esperar que seus usuários aceitassem a interface sugerida pelo código mais simples ainda era legal. A HP nos deu RPN e gostamos . Pensando como um 201 * -er você obtém 1280 caracteres de inchaço.
— usar o seguinte comando

5

Meteoro: 575 caracteres

Eu me diverti muito com este! O aplicativo está disponível em http://cgchat.meteor.com/ .

chat.html: 171 caracteres

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

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

client / client.js: 359 caracteres

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

Link agora está morto.
— programmer5000

5

Javascript do nó / meteoro + html + css + websocket: 1.105 bytes

Aqui está um usando node.js / meteor . Obviamente escrito em js, em tempo real e usando websockets. Usa os pacotes internos padrão do meteoro.

Poderia ser muito menor. Também é persistente por meio do mongo incluído (não que isso seja uma coisa boa).

Uma captura de tela de trabalho:

insira a descrição da imagem aqui

Para executar, instale o meteoro.

Linux:

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

Windows: win.meteor.com

Clone meu repositório e execute o meteoro:

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

aponte seu navegador para localhost: 3000

chat.js: 703 bytes (cliente / servidor):

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>

1
Bem-vindo ao codegolf! Esse arquivo chat.htmlparece ter apenas 254 bytes. Observe que os navegadores não são muito exigentes - não me preocupo em fechar as tags e você definitivamente não precisa da barra no final das tags (a menos que o nó exija isso). Além disso, mate mais espaço em branco! Eu vejo um par no javascript, e muito no html.
— Boothby
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.