renaming/deleting

:wq
This commit is contained in:
Peter Harpending 2025-12-12 23:21:00 -08:00
parent ff257ae976
commit cbfc496057
8 changed files with 48 additions and 561 deletions

View File

@ -1,105 +0,0 @@
-module(et_piece).
-vsn("1.0.4").
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").
-license("MIT").
-export([rand/0, new/1, flip/2, points/2, points/1, type/1, sides/1]).
-export_type([data/0]).
-record(p,
{flip = 1 :: 1..4,
type = i :: erltris:type()}).
-opaque data() :: #p{}.
rand() ->
case rand:uniform(7) of
1 -> new(i);
2 -> new(o);
3 -> new(t);
4 -> new(s);
5 -> new(z);
6 -> new(j);
7 -> new(l)
end.
new(T) -> #p{type = T}.
flip(r, Piece = #p{flip = 4}) -> Piece#p{flip = 1};
flip(r, Piece = #p{flip = F}) -> Piece#p{flip = F + 1};
flip(l, Piece = #p{flip = 1}) -> Piece#p{flip = 4};
flip(l, Piece = #p{flip = F}) -> Piece#p{flip = F - 1}.
points(Piece, {LX, LY}) ->
Offsets = points(Piece),
Translate = fun({OX, OY}) -> {LX + OX, LY + OY} end,
lists:map(Translate, Offsets).
points(#p{flip = F, type = T}) ->
offset(T, F).
offset(i, 1) -> [{0, 2}, {1, 2}, {2, 2}, {3, 2}];
offset(i, 2) -> [{2, 3}, {2, 2}, {2, 1}, {2, 0}];
offset(i, 3) -> [{0, 1}, {1, 1}, {2, 1}, {3, 1}];
offset(i, 4) -> [{1, 3}, {1, 2}, {1, 1}, {1, 0}];
offset(o, _) -> [{1, 1}, {1, 2}, {2, 1}, {2, 2}];
offset(t, 1) -> [{0, 1}, {1, 1}, {2, 1}, {1, 2}];
offset(t, 2) -> [{1, 2}, {1, 1}, {1, 0}, {2, 1}];
offset(t, 3) -> [{0, 1}, {1, 1}, {2, 1}, {1, 0}];
offset(t, 4) -> [{1, 2}, {1, 1}, {1, 0}, {0, 1}];
offset(s, 1) -> [{0, 1}, {1, 1}, {1, 2}, {2, 2}];
offset(s, 2) -> [{1, 2}, {1, 1}, {2, 1}, {2, 0}];
offset(s, 3) -> [{0, 0}, {1, 0}, {1, 1}, {2, 1}];
offset(s, 4) -> [{0, 2}, {0, 1}, {1, 1}, {1, 0}];
offset(z, 1) -> [{0, 2}, {1, 2}, {1, 1}, {2, 1}];
offset(z, 2) -> [{1, 0}, {1, 1}, {2, 1}, {2, 2}];
offset(z, 3) -> [{0, 1}, {1, 1}, {1, 0}, {2, 0}];
offset(z, 4) -> [{0, 0}, {0, 1}, {1, 1}, {1, 2}];
offset(j, 1) -> [{0, 2}, {0, 1}, {1, 1}, {2, 1}];
offset(j, 2) -> [{1, 0}, {1, 1}, {1, 2}, {2, 2}];
offset(j, 3) -> [{0, 1}, {1, 1}, {2, 1}, {2, 0}];
offset(j, 4) -> [{0, 0}, {1, 0}, {1, 1}, {1, 2}];
offset(l, 1) -> [{0, 1}, {1, 1}, {2, 1}, {2, 2}];
offset(l, 2) -> [{1, 2}, {1, 1}, {1, 0}, {2, 0}];
offset(l, 3) -> [{0, 0}, {0, 1}, {1, 1}, {2, 1}];
offset(l, 4) -> [{0, 2}, {1, 2}, {1, 1}, {1, 0}].
type(#p{type = T}) -> T.
sides(#p{type = T, flip = F}) ->
sides(T, F).
sides(i, 1) -> {0, 3, 2};
sides(i, 2) -> {2, 2, 3};
sides(i, 3) -> {0, 3, 1};
sides(i, 4) -> {1, 1, 3};
sides(o, _) -> {1, 2, 2};
sides(t, 1) -> {0, 2, 2};
sides(t, 2) -> {1, 2, 2};
sides(t, 3) -> {0, 2, 1};
sides(t, 4) -> {0, 1, 2};
sides(s, 1) -> {0, 2, 2};
sides(s, 2) -> {1, 2, 2};
sides(s, 3) -> {0, 2, 1};
sides(s, 4) -> {0, 1, 2};
sides(z, 1) -> {0 ,2, 2};
sides(z, 2) -> {1, 2, 2};
sides(z, 3) -> {0 ,2, 1};
sides(z, 4) -> {0, 1, 2};
sides(j, 1) -> {0, 2, 2};
sides(j, 2) -> {1, 2, 2};
sides(j, 3) -> {0, 2, 1};
sides(j, 4) -> {0, 1, 2};
sides(l, 1) -> {0, 2, 2};
sides(l, 2) -> {1, 2, 2};
sides(l, 3) -> {0, 2, 1};
sides(l, 4) -> {0, 1, 2}.

View File

@ -1,79 +0,0 @@
-module(et_well).
-vsn("1.0.4").
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").
-license("MIT").
-export([new/0, new/2,
dimensions/1, height/1, width/1,
fetch/3, store/4, complete/1, collapse/2]).
-export_type([playfield/0]).
-opaque playfield() :: tuple().
new() ->
new(10, 20).
new(W, H) ->
erlang:make_tuple(H, row(W)).
row(W) ->
erlang:make_tuple(W, x).
dimensions(Well) ->
H = size(Well),
W = size(element(1, Well)),
{W, H}.
height(Well) ->
size(Well).
width(Well) ->
size(element(1, Well)).
fetch(Well, X, Y) ->
element(X, element(Y, Well)).
store(Well, Value, X, Y) ->
setelement(Y, Well, setelement(X, element(Y, Well), Value)).
complete(Well) ->
{W, H} = dimensions(Well),
complete(H, W, Well, []).
complete(Y, W, Well, Lines) when Y >= 1 ->
case line_complete(W, element(Y, Well)) of
true -> complete(Y - 1, W, Well, [Y | Lines]);
false -> complete(Y - 1, W, Well, Lines)
end;
complete(_, _, _, Lines) ->
Lines.
line_complete(X, Line) when X >= 1 ->
case element(X, Line) of
x -> false;
_ -> line_complete(X - 1, Line)
end;
line_complete(_, _) ->
true.
collapse(Well, Lines) ->
Blank = row(width(Well)),
Crunch =
fun(L, {W, Count}) ->
Crunched = erlang:insert_element(1, erlang:delete_element(L, W), Blank),
{Crunched, Count + 1}
end,
lists:foldl(Crunch, {Well, 0}, Lines).

View File

@ -1,262 +0,0 @@
% @doc
% controller for chat
-module(fd_chat).
-vsn("0.1.0").
-behavior(gen_server).
-author("Peter Harpending <peterharpending@qpq.swiss>").
-copyright("Peter Harpending <peterharpending@qpq.swiss>").
-license("BSD-2-Clause-FreeBSD").
-export([
join/1,
relay/1,
nick_available/1
]).
-export([start_link/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
code_change/3, terminate/2]).
-include("$zx_include/zx_logger.hrl").
-record(o, {pid :: pid(),
nick :: string()}).
-type orator() :: #o{}.
-record(s, {orators = [] :: [orator()]}).
-type state() :: #s{}.
%%% Service Interface
-spec join(Nick) -> Result
when Nick :: string(),
Result :: ok
| {error, Reason :: any()}.
join(Nick) ->
gen_server:call(?MODULE, {join, Nick}).
-spec nick_available(Nick) -> Result
when Nick :: string(),
Result :: boolean().
nick_available(Nick) ->
gen_server:call(?MODULE, {nick_available, Nick}).
-spec relay(Message) -> ok
when Message :: string().
relay(Message) ->
gen_server:cast(?MODULE, {relay, self(), Message}).
%%% Startup Functions
-spec start_link() -> Result
when Result :: {ok, pid()}
| {error, Reason :: term()}.
%% @private
%% This should only ever be called by fd_chat_orators (the service-level supervisor).
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, none, []).
-spec init(none) -> {ok, state()}.
%% @private
%% Called by the supervisor process to give the process a chance to perform any
%% preparatory work necessary for proper function.
init(none) ->
ok = tell("~p Starting.", [?MODULE]),
State = #s{},
{ok, State}.
%%% gen_server Message Handling Callbacks
-spec handle_call(Message, From, State) -> Result
when Message :: term(),
From :: {pid(), reference()},
State :: state(),
Result :: {reply, Response, NewState}
| {noreply, State},
Response :: term(),
NewState :: state().
%% @private
%% The gen_server:handle_call/3 callback.
%% See: http://erlang.org/doc/man/gen_server.html#Module:handle_call-3
handle_call({join, Nick}, {Pid, _}, State) ->
{Reply, NewState} = do_join(Pid, Nick, State),
{reply, Reply, NewState};
handle_call({nick_available, Nick}, _, State = #s{orators = Orators}) ->
Reply = is_nick_available(Nick, Orators),
{reply, Reply, State};
handle_call(Unexpected, From, State) ->
ok = tell("~p Unexpected call from ~tp: ~tp~n", [?MODULE, From, Unexpected]),
{noreply, State}.
-spec handle_cast(Message, State) -> {noreply, NewState}
when Message :: term(),
State :: state(),
NewState :: state().
%% @private
%% The gen_server:handle_cast/2 callback.
%% See: http://erlang.org/doc/man/gen_server.html#Module:handle_cast-2
handle_cast({relay, From, Message}, State = #s{orators = Orators}) ->
do_relay(From, Message, Orators),
{noreply, State};
handle_cast(Unexpected, State) ->
ok = tell("~p Unexpected cast: ~tp~n", [?MODULE, Unexpected]),
{noreply, State}.
-spec handle_info(Message, State) -> {noreply, NewState}
when Message :: term(),
State :: state(),
NewState :: state().
%% @private
%% The gen_server:handle_info/2 callback.
%% See: http://erlang.org/doc/man/gen_server.html#Module:handle_info-2
handle_info(Msg = {'DOWN', _Mon, process, _Pid, _Reason}, State) ->
NewState = handle_down(Msg, State),
{noreply, NewState};
handle_info(Unexpected, State) ->
ok = tell("~p Unexpected info: ~tp~n", [?MODULE, Unexpected]),
{noreply, State}.
%%% OTP Service Functions
-spec code_change(OldVersion, State, Extra) -> Result
when OldVersion :: {down, Version} | Version,
Version :: term(),
State :: state(),
Extra :: term(),
Result :: {ok, NewState}
| {error, Reason :: term()},
NewState :: state().
%% @private
%% The gen_server:code_change/3 callback.
%% See: http://erlang.org/doc/man/gen_server.html#Module:code_change-3
code_change(_, State, _) ->
{ok, State}.
-spec terminate(Reason, State) -> no_return()
when Reason :: normal
| shutdown
| {shutdown, term()}
| term(),
State :: state().
%% @private
%% The gen_server:terminate/2 callback.
%% See: http://erlang.org/doc/man/gen_server.html#Module:terminate-2
terminate(_, _) ->
ok.
%%% internals
-spec do_join(Pid, Nick, State) -> {Reply, NewState}
when Pid :: pid(),
Nick :: string(),
Reply :: ok | {error, Reason :: any()},
NewState :: State.
do_join(Pid, Nick, State = #s{orators = Orators}) ->
case ensure_can_join(Pid, Nick, Orators) of
ok -> do_join2(Pid, Nick, State);
Error -> {Error, State}
end.
do_join2(Pid, Nick, State = #s{orators = Orators}) ->
_Monitor = erlang:monitor(process, Pid),
NewOrator = #o{pid = Pid, nick = Nick},
NewOrators = [NewOrator | Orators],
NewState = State#s{orators = NewOrators},
{ok, NewState}.
-spec ensure_can_join(Pid, Nick, Orators) -> Result
when Pid :: pid(),
Nick :: string(),
Orators :: [orator()],
Result :: ok
| {error, Reason},
Reason :: any().
% @private
% ensures both Pid and Nick are unique
ensure_can_join(Pid, _ , [#o{pid = Pid} | _ ]) -> {error, already_joined};
ensure_can_join(_ , Nick, [#o{nick = Nick} | _ ]) -> {error, {nick_taken, Nick}};
ensure_can_join(Pid, Nick, [_ | Rest]) -> ensure_can_join(Pid, Nick, Rest);
ensure_can_join(_ , _ , [] ) -> ok.
-spec is_nick_available(Nick, Orators) -> boolean()
when Nick :: string(),
Orators :: [orator()].
is_nick_available(Nick, [#o{nick = Nick} | _ ]) -> false;
is_nick_available(Nick, [_ | Rest]) -> is_nick_available(Nick, Rest);
is_nick_available(_ , [] ) -> true.
-spec handle_down(Msg, State) -> NewState
when Msg :: {'DOWN', Mon, process, Pid, Reason},
Mon :: erlang:monitor(),
Pid :: pid(),
Reason :: any(),
State :: state(),
NewState :: State.
handle_down(Msg = {'DOWN', _, process, Pid, _}, State = #s{orators = Orators}) ->
NewOrators = hdn(Msg, Pid, Orators, []),
NewState = State#s{orators = NewOrators},
NewState.
% encountered item, removing
hdn(_, Pid, [#o{pid = Pid} | Rest], Acc) -> Rest ++ Acc;
hdn(Msg, Pid, [Skip | Rest], Acc) -> hdn(Msg, Pid, Rest, [Skip | Acc]);
hdn(Msg, _, [] , Acc) ->
log("~tp: Unexpected message: ~tp", [?MODULE, Msg]),
Acc.
do_relay(Pid, Message, Orators) ->
case lists:keyfind(Pid, #o.pid, Orators) of
#o{nick = Nick} ->
do_relay2(Nick, Message, Orators);
false ->
tell("~tp: Message received from outsider ~tp: ~tp", [?MODULE, Pid, Message]),
error
end.
% skip
do_relay2(Nick, Msg, [#o{nick = Nick} | Rest]) ->
do_relay2(Nick, Msg, Rest);
do_relay2(Nick, Msg, [#o{pid = Pid} | Rest]) ->
Pid ! {chat, {relay, Nick, Msg}},
do_relay2(Nick, Msg, Rest);
do_relay2(_, _, []) ->
ok.

33
src/fd_httpd.erl Normal file
View File

@ -0,0 +1,33 @@
-module(fd_httpd).
-vsn("0.1.0").
-behaviour(supervisor).
-author("Peter Harpending <peterharpending@qpq.swiss>").
-copyright("Peter Harpending <peterharpending@qpq.swiss>").
-license("BSD-2-Clause-FreeBSD").
-export([start_link/0]).
-export([init/1]).
-spec start_link() -> {ok, pid()}.
%% @private
%% This supervisor's own start function.
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
-spec init([]) -> {ok, {supervisor:sup_flags(), [supervisor:child_spec()]}}.
%% @private
%% The OTP init/1 function.
init([]) ->
RestartStrategy = {one_for_one, 1, 60},
Clerks = {fd_httpd_clerks,
{fd_httpd_clerks, start_link, []},
permanent,
5000,
supervisor,
[fd_httpd_clerks]},
Children = [Clerks],
{ok, {RestartStrategy, Children}}.

View File

@ -1,14 +1,14 @@
%%% @doc
%%% front end web development lab Client Service Supervisor
%%% front end web development lab Clerk Service Supervisor
%%%
%%% This is the service-level supervisor of the system. It is the parent of both the
%%% client connection handlers and the client manager (which manages the client
%%% clerk connection handlers and the clerk manager (which manages the clerk
%%% connection handlers). This is the child of fd_sup.
%%%
%%% See: http://erlang.org/doc/apps/kernel/application.html
%%% @end
-module(fd_http).
-module(fd_httpd_clerks).
-vsn("0.1.0").
-behavior(supervisor).
-author("Peter Harpending <peterharpending@qpq.swiss>").
@ -32,17 +32,17 @@ start_link() ->
init(none) ->
RestartStrategy = {rest_for_one, 1, 60},
HttpClientMan = {fd_http_client_man,
{fd_http_client_man, start_link, []},
HttpClerkMan = {fd_http_clerk_man,
{fd_http_clerk_man, start_link, []},
permanent,
5000,
worker,
[fd_http_client_man]},
HttpClientSup = {fd_http_client_sup,
{fd_http_client_sup, start_link, []},
[fd_http_clerk_man]},
HttpClerkSup = {fd_http_clerk_sup,
{fd_http_clerk_sup, start_link, []},
permanent,
5000,
supervisor,
[fd_http_client_sup]},
Children = [HttpClientSup, HttpClientMan],
[fd_http_clerk_sup]},
Children = [HttpClerkSup, HttpClerkMan],
{ok, {RestartStrategy, Children}}.

View File

@ -1,5 +1,5 @@
% @doc static file cache
-module(fd_sfc).
-module(fd_httpd_sfc).
-behavior(gen_server).

View File

@ -36,29 +36,17 @@ start_link() ->
init([]) ->
RestartStrategy = {one_for_one, 1, 60},
Httpd = {fd_http,
{fd_http, start_link, []},
Httpd = {fd_httpd,
{fd_httpd, start_link, []},
permanent,
5000,
supervisor,
[fd_clients]},
Chat = {fd_chat,
{fd_chat, start_link, []},
permanent,
5000,
worker,
[fd_chat]},
FileCache = {fd_sfc,
{fd_sfc, start_link, []},
permanent,
5000,
worker,
[fd_sfc]},
[fd_httpd]},
Cache = {fd_cache,
{fd_cache, start_link, []},
permanent,
5000,
worker,
[fd_cache]},
Children = [Httpd, Chat, FileCache, Cache],
Children = [Httpd, Cache],
{ok, {RestartStrategy, Children}}.

View File

@ -1,88 +0,0 @@
% @doc tetris
%
% manages state for a single game of tetris
%
% sends parent process messages `{tetris, String}` where String is an encoded
% JSON blob meant to be sent to the page script in /priv/static/js/ts/tetris.ts
%
% Refs:
% 1. https://www.erlang.org/docs/24/man/gen_server
-module(fd_tetris).
-behavior(gen_server).
-export([
%% caller context
start_link/0,
%% process context
%% gen_server callbacks
init/1, handle_call/3, handle_cast/2, handle_info/2,
code_change/3, terminate/2
]).
-include("$zx_include/zx_logger.hrl").
-record(s, {parent :: pid()}).
-type state() :: #s{}.
%%-----------------------------------------------------------------------------
%% caller context below this line
%%-----------------------------------------------------------------------------
-spec ws_msg(Tetris, Message) -> ok
when Tetris :: pid(),
Message :: qhl_ws:ws_msg().
ws_msg(Tetris, Msg) ->
gen_server:cast(Tetris, {ws_msg, Msg}).
-spec start_link() -> {ok, pid()} | {error, term()}.
start_link() ->
gen_server:start_link(?MODULE, [self()], []).
%%-----------------------------------------------------------------------------
%% process context below this line
%%-----------------------------------------------------------------------------
%% gen_server callbacks
-spec init(Args) -> {ok, State}
when Args :: [Parent],
Parent :: pid(),
State :: state().
init([Parent]) ->
tell("~tp:~tp starting fd_tetris with parent ~p", [?MODULE, self(), Parent]),
self() ! {poop, 0},
InitState = #s{parent = Parent},
{ok, InitState}.
handle_call(Unexpected, From, State) ->
tell("~tp:~tp unexpected call from ~tp: ~tp", [?MODULE, self(), From, Unexpected]),
{noreply, State}.
handle_cast(Unexpected, State) ->
tell("~tp:~tp unexpected cast: ~tp", [?MODULE, self(), Unexpected]),
{noreply, State}.
handle_info({poop, N}, State = #s{parent = Parent}) ->
Parent ! {tetris, io_lib:format("poop~p", [N])},
erlang:send_after(1_000, self(), {poop, N+1}),
{noreply, State};
handle_info(Unexpected, State) ->
tell("~tp:~tp unexpected info: ~tp", [?MODULE, self(), Unexpected]),
{noreply, State}.
code_change(_, State, _) ->
{ok, State}.
terminate(_, _) ->
ok.