Add more OTP implementation of Speed Daemon - sdball/protohackers
- Author: Stephen Ball
- Published:
-
- Permalink: /blog/add-more-otp-implementation-of-speed-daemon
Commit dd3e855 from github.com/sdball/protohackers
Thanks again to @whatyouhide for the example code. I added it to this repo by retyping (and somewhat tweaking) the reference implementation.
I learned a lot of tricks about using kernel functions like update_in
and put_in
to handle updating nested state.
The approach to have the binary protocol functions in their own module was very nice. I learned some good tricks for more idiomatically matching binary messages as well.
e.g.
<<@dispatcher, roads_count::8, roads::binary-size(roads_count * 2), rest::binary>>
vs
def client_message(<<@dispatcher, roads_count::8, rest::binary>>) do
case rest do
<<roads::binary-size(roads_count * 2), rest::binary>> ->
Logger.info("SLS.ClientMessage.dispatcher roads=#{inspect(roads)}")
{:ok, dispatcher: Dispatcher.new(roads), rest: rest}
_incomplete ->
:partial
end
end
That is, using roads_count
to further match within the same binary
pattern instead of having a secondary pattern match like I was doing
originally.
It’s always a good idea to consider (and implement!) alternatives but I do prefer some aspects of my original approach to handling the generation of tickets from observations.
- A MapSet is a nice way to ensure uniqueness for ticketed plates by day.
- I didn’t generate any new tickets if a ticket was already generated for the given days covered by a new violation.
- I also didn’t regenerate all tickets for a given observation’s road and plate but only checked the observations before and after the new observation to potentially generate 0, 1, or 2 new tickets from potential violations.
Happily, like for MITM, my existing integration tests for the Speed Daemon server worked against this new implementation as well. Hooray!
dd3e8553403083e6b8b83bf53ca3b1b0de76e6fe on sdball/protohackers