Single player game close to finished
This commit is contained in:
parent
3385118b14
commit
584b1c9ef9
12 changed files with 179 additions and 6454 deletions
|
|
@ -1,3 +1,4 @@
|
|||
import components.{click_cell}
|
||||
import gleam/erlang/process.{type Subject}
|
||||
import gleam/int
|
||||
import gleam/list
|
||||
|
|
@ -24,6 +25,8 @@ pub fn component() -> lustre.App(
|
|||
pub opaque type Model {
|
||||
Model(
|
||||
state: Msg,
|
||||
players: List(#(String, String)),
|
||||
player_id: Option(String),
|
||||
answers: List(#(Int, #(String, String))),
|
||||
handler: Started(Subject(NotifyServer)),
|
||||
)
|
||||
|
|
@ -48,122 +51,136 @@ fn init(
|
|||
#(a, #(b, ""))
|
||||
})
|
||||
|
||||
#(Model(Initial, initial_array, handler), effect.none())
|
||||
#(
|
||||
Model(
|
||||
Initial,
|
||||
actor.call(handler.data, 1000, message.FetchPlayers),
|
||||
None,
|
||||
initial_array,
|
||||
handler,
|
||||
),
|
||||
effect.none(),
|
||||
)
|
||||
}
|
||||
|
||||
pub opaque type Msg {
|
||||
Initial
|
||||
PickedName(name: String)
|
||||
SharedMessage(message: NotifyClient)
|
||||
ReceiveName(message: String)
|
||||
AcceptName(accept: Option(String))
|
||||
GiveQuestion(name: String, question: String)
|
||||
GiveAnswer(name: String, question: Int, answer: String)
|
||||
PickQuestion
|
||||
PickedQuestion(question: String)
|
||||
GiveAnswer(question: String, answer: String)
|
||||
}
|
||||
|
||||
fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
|
||||
case msg {
|
||||
Initial | SharedMessage(_) -> #(model, effect.none())
|
||||
AcceptName(None) -> #(Model(Initial, [], model.handler), effect.none())
|
||||
AcceptName(Some(name)) -> {
|
||||
#(Model(..model, state: GiveQuestion(name, "")), effect.none())
|
||||
}
|
||||
GiveQuestion(name, question) ->
|
||||
case int.parse(question) {
|
||||
Ok(question) if question >= 1 && question <= 14 -> #(
|
||||
Model(..model, state: GiveAnswer(name:, question:, answer: "")),
|
||||
effect.none(),
|
||||
)
|
||||
_ -> #(
|
||||
Model(..model, state: GiveQuestion(name:, question: "")),
|
||||
effect.none(),
|
||||
)
|
||||
}
|
||||
GiveAnswer(id, question, answer) -> {
|
||||
actor.send(
|
||||
model.handler.data,
|
||||
message.GiveSingleAnswer(id:, question:, answer:),
|
||||
)
|
||||
let new_value = case list.key_find(model.answers, question) {
|
||||
Ok(pair) -> {
|
||||
let #(a, _) = pair
|
||||
#(a, answer)
|
||||
}
|
||||
Error(_) -> #("", answer)
|
||||
}
|
||||
Initial -> #(Model(..model, state: msg), effect.none())
|
||||
PickedName(player_id) -> #(
|
||||
Model(..model, player_id: Some(player_id), state: PickQuestion),
|
||||
effect.none(),
|
||||
)
|
||||
SharedMessage(_) -> #(model, effect.none())
|
||||
AcceptName(None) -> #(
|
||||
Model(Initial, model.players, None, [], model.handler),
|
||||
effect.none(),
|
||||
)
|
||||
AcceptName(Some(player_id)) -> {
|
||||
#(
|
||||
Model(
|
||||
..model,
|
||||
state: GiveQuestion(id, ""),
|
||||
answers: list.key_set(model.answers, question, new_value),
|
||||
),
|
||||
Model(..model, player_id: Some(player_id), state: PickQuestion),
|
||||
effect.none(),
|
||||
)
|
||||
}
|
||||
PickQuestion -> #(model, effect.none())
|
||||
PickedQuestion(question) -> {
|
||||
#(Model(..model, state: GiveAnswer(question, "")), effect.none())
|
||||
}
|
||||
GiveAnswer(question, answer) -> {
|
||||
let assert Some(player_id) = model.player_id
|
||||
case int.parse(question) {
|
||||
Ok(question) -> {
|
||||
actor.send(
|
||||
model.handler.data,
|
||||
message.GiveSingleAnswer(id: player_id, question:, answer:),
|
||||
)
|
||||
let new_value = case list.key_find(model.answers, question) {
|
||||
Ok(pair) -> {
|
||||
let #(a, _) = pair
|
||||
#(a, answer)
|
||||
}
|
||||
Error(_) -> #("", answer)
|
||||
}
|
||||
#(
|
||||
Model(
|
||||
..model,
|
||||
state: PickQuestion,
|
||||
answers: list.key_set(model.answers, question, new_value),
|
||||
),
|
||||
effect.none(),
|
||||
)
|
||||
}
|
||||
_ -> {
|
||||
echo "bad index"
|
||||
#(model, effect.none())
|
||||
}
|
||||
}
|
||||
}
|
||||
ReceiveName(_) -> #(Model(..model, state: msg), effect.none())
|
||||
}
|
||||
}
|
||||
|
||||
fn view(model: Model) -> Element(Msg) {
|
||||
element.fragment([
|
||||
html.div([attribute.class("terminal-prompt")], [
|
||||
case model.state {
|
||||
Initial ->
|
||||
step_prompt(
|
||||
"Hello stranger. To join the quiz, I need to know your name",
|
||||
fn() { view_input(ReceiveName) },
|
||||
)
|
||||
ReceiveName(name) ->
|
||||
step_prompt(
|
||||
"Your name is " <> name <> "? Are you absolutely sure???",
|
||||
fn() { view_yes_no(name, AcceptName) },
|
||||
)
|
||||
GiveQuestion(name, _) ->
|
||||
step_prompt(
|
||||
"Enter the number of the question you want to answer",
|
||||
fn() { view_named_input(name, GiveQuestion) },
|
||||
)
|
||||
GiveAnswer(name, question, _) ->
|
||||
step_prompt(
|
||||
"Enter the answer to question number " <> int.to_string(question),
|
||||
fn() { view_named_keyed_input(question, name, GiveAnswer) },
|
||||
)
|
||||
_ -> html.h3([], [html.text("Waiting for next question")])
|
||||
},
|
||||
]),
|
||||
html.div([class("terminal-header")], [
|
||||
html.div([class("terminal-status")], [
|
||||
html.span([class("status-blink")], [html.text("●")]),
|
||||
html.text(" SYSTEM READY"),
|
||||
html.span([class("ml-8")], [
|
||||
case model.state {
|
||||
Initial -> html.text("STATUS: Please input your name")
|
||||
Initial -> html.text("STATUS: Please select player")
|
||||
ReceiveName(_) -> html.text("STATUS: Please validate your name")
|
||||
GiveQuestion(_, _) -> html.text("STATUS: Pick question to answer")
|
||||
GiveAnswer(_, _, _) -> html.text("STATUS: Give your answer")
|
||||
PickQuestion -> html.text("STATUS: Pick question to answer")
|
||||
GiveAnswer(_, _) -> html.text("STATUS: Give your answer")
|
||||
_ -> html.text("STATUS: Waiting for next question")
|
||||
},
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
terminal_section(model.answers, "[ACTIVE TRANSMISSIONS]", fn(answer) {
|
||||
content_cell(answer)
|
||||
}),
|
||||
html.div([attribute.class("terminal-section")], [
|
||||
html.div([attribute.class("terminal-label mb-4")], [
|
||||
html.text("[ACTIVE TRANSMISSIONS]"),
|
||||
]),
|
||||
]),
|
||||
case model.state {
|
||||
Initial -> view_players(model.players)
|
||||
PickQuestion -> view_questions(model.answers)
|
||||
_ -> content_cell(#(10, #("Answer", "Answer question")))
|
||||
},
|
||||
])
|
||||
}
|
||||
|
||||
fn terminal_section(
|
||||
answers: List(#(Int, #(String, String))),
|
||||
header: String,
|
||||
extract: fn(#(Int, #(String, String))) -> Element(Msg),
|
||||
) {
|
||||
html.div([attribute.class("terminal-section")], [
|
||||
html.div([attribute.class("terminal-label mb-4")], [
|
||||
html.text(header),
|
||||
]),
|
||||
html.div([attribute.class("singles-grid")], list.map(answers, extract)),
|
||||
fn view_players(players: List(#(String, String))) {
|
||||
html.div([], [
|
||||
html.div(
|
||||
[],
|
||||
list.append(
|
||||
list.index_map(players, fn(item, index) {
|
||||
click_cell(Some(int.to_string(index)), item, PickedName)
|
||||
}),
|
||||
[click_cell(Some("NEW"), #("new", "New Player!"), PickedName)],
|
||||
),
|
||||
),
|
||||
])
|
||||
}
|
||||
|
||||
fn view_questions(answers: List(#(Int, #(String, String)))) {
|
||||
html.div(
|
||||
[attribute.class("singles-grid")],
|
||||
list.map(answers, fn(content) { content_cell(content) }),
|
||||
)
|
||||
}
|
||||
|
||||
fn content_cell(answer: #(Int, #(String, String))) -> Element(Msg) {
|
||||
let #(question, #(question_text, answer)) = answer
|
||||
html.div(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue