telnet接続で計算問題を出題する |
http://mymo.blog8.fc2.com/blog-entry-35.html
これをErlangでやってみました。
%% -*- coding: utf-8 -*-
-module(sample).
-export([start/0, handle_connection/1, recv_loop/2]).
start() ->
{ok, ListenSocket} = gen_tcp:listen(9999, [{active, false}, binary, {packet, line},{reuseaddr, true}]),
accept(ListenSocket).
accept(ListenSocket) ->
{ok, Socket} = gen_tcp:accept(ListenSocket),
spawn(?MODULE, handle_connection, [Socket]),
accept(ListenSocket).
handle_connection(Socket) ->
A = random:uniform(99),
B = random:uniform(99),
Opeid = random:uniform(4),
Opech = string:substr("+-*/", Opeid, 1),
%% 問題は、1から99までの任意の値2つの四則算
Problem = io_lib:format("~.10b ~s ~.10b\r\n", [A, Opech, B]),
%% 事前に正解を計算しておく
Ans = calc(A, B, Opeid),
gen_tcp:send(Socket, Problem),
recv_loop(Socket, Ans).
recv_loop(Socket, Ans) ->
case gen_tcp:recv(Socket, 0) of
{ok, B} ->
case B of
<<"bye\r\n">> ->
gen_tcp:send(Socket, <<"bye\r\n">>),
gen_tcp:close(Socket);
Other ->
{ClientAns, _} = string:to_integer(binary_to_list(Other)),
Result = check_ans(Ans, ClientAns),
gen_tcp:send(Socket, Result),
handle_connection(Socket)
end;
{error, closed} ->
ok
end.
%% 正解の場合の応答
check_ans(Ans, ClientAns) when is_integer(ClientAns), Ans =:= ClientAns ->
<<"\r\nOK!\r\n">>;
%% 不正解の場合の応答
check_ans(_, _) ->
<<"\r\nNG!\r\n">>.
%% Calculation answer
calc(A, B, 1) -> A + B;
calc(A, B, 2) -> A - B;
calc(A, B, 3) -> A * B;
calc(A, B, 4) -> A div B.
binary_to_list(Other)
これがミソ
最初
io_lib:format("~s", [Other])
としていたのですが、改行とかがよくわからん文字に変換されていたようで、
string:to_integerがどうやっても失敗する。
簡単にできるとおもっていたのに、意外と苦戦しました。
【参考URL】
Erlang で echo server
乱数からIDを作る
STDLIB Reference Manual