fix device
This commit is contained in:
parent
3b7d669a5d
commit
f055fc7c0f
3 changed files with 108 additions and 24 deletions
|
|
@ -246,7 +246,7 @@ function handleApiMessage(e: MessageEvent) {
|
|||
return;
|
||||
}
|
||||
|
||||
console.log("API recv", message.type);
|
||||
console.log("API recv", message);
|
||||
if (message.type !== "device_event") return;
|
||||
const socket = sockets.get(message.deviceId);
|
||||
if (!socket) {
|
||||
|
|
@ -274,6 +274,7 @@ function handleApiMessage(e: MessageEvent) {
|
|||
|
||||
if (event.type === "party_status") {
|
||||
const quizData = event.party?.data ?? null;
|
||||
console.log("API quizData", quizData);
|
||||
if (!quizData) return;
|
||||
if (quizData.status === "results") {
|
||||
writeProxyOutput(socket, "Results");
|
||||
|
|
|
|||
|
|
@ -38,26 +38,26 @@ pub struct QuestionData {
|
|||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct QuestionDataNet<'a> {
|
||||
pub text: &'a str,
|
||||
pub struct QuestionDataNet {
|
||||
pub text: String,
|
||||
pub q_type: QuestionType,
|
||||
pub points: i32,
|
||||
pub index: usize,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub enum ProxyOutput<'a> {
|
||||
ConnectPrompt(&'a str),
|
||||
WaitingForParty(&'a str),
|
||||
Question(QuestionDataNet<'a>),
|
||||
pub enum ProxyOutput {
|
||||
ConnectPrompt(String),
|
||||
WaitingForParty(String),
|
||||
Question(QuestionDataNet),
|
||||
Results,
|
||||
Error(&'a str),
|
||||
Error(String),
|
||||
}
|
||||
|
||||
impl<'a> From<QuestionDataNet<'a>> for QuestionData {
|
||||
fn from(value: QuestionDataNet<'a>) -> Self {
|
||||
impl From<QuestionDataNet> for QuestionData {
|
||||
fn from(value: QuestionDataNet) -> Self {
|
||||
QuestionData {
|
||||
text: OwnedStr::from_str(value.text).unwrap(),
|
||||
text: OwnedStr::from_str(value.text.as_str()).unwrap(),
|
||||
q_type: value.q_type,
|
||||
points: value.points,
|
||||
index: value.index,
|
||||
|
|
@ -135,7 +135,7 @@ impl DeviceState {
|
|||
&mut self.wheel
|
||||
}
|
||||
|
||||
pub fn apply_proxy_output(&mut self, data: ProxyOutput<'_>) {
|
||||
pub fn apply_proxy_output(&mut self, data: ProxyOutput) {
|
||||
match data {
|
||||
ProxyOutput::ConnectPrompt(device_id) => {
|
||||
let mut owned_device_id = OwnedStr::new();
|
||||
|
|
@ -161,11 +161,32 @@ impl DeviceState {
|
|||
}
|
||||
ProxyOutput::Question(data) => {
|
||||
let data: QuestionData = data.into();
|
||||
let mut future_wheel = WheelData::empty();
|
||||
if let QuestionType::Numeric { min, max } = data.q_type {
|
||||
future_wheel.max = max;
|
||||
future_wheel.min = min;
|
||||
future_wheel.value = (min + max) / 2;
|
||||
let same_question = self
|
||||
.question
|
||||
.as_ref()
|
||||
.is_some_and(|question| question.index == data.index);
|
||||
let mut future_wheel = if same_question {
|
||||
self.wheel
|
||||
} else {
|
||||
WheelData::empty()
|
||||
};
|
||||
match data.q_type {
|
||||
QuestionType::Numeric { min, max } => {
|
||||
future_wheel.max = max;
|
||||
future_wheel.min = min;
|
||||
if same_question {
|
||||
future_wheel.value = future_wheel.value.clamp(min, max);
|
||||
} else {
|
||||
future_wheel.value = (min + max) / 2;
|
||||
}
|
||||
}
|
||||
QuestionType::Choice => {
|
||||
future_wheel = WheelData::empty();
|
||||
}
|
||||
}
|
||||
if !same_question {
|
||||
self.last_index = data.index;
|
||||
self.title_offset = 0;
|
||||
}
|
||||
self.question = Some(data);
|
||||
self.view = ViewState::Question;
|
||||
|
|
@ -235,10 +256,7 @@ impl DeviceState {
|
|||
break;
|
||||
}
|
||||
}
|
||||
return Some((
|
||||
display_name,
|
||||
OwnedStr::from_str("Awaiting party").unwrap(),
|
||||
));
|
||||
return Some((display_name, OwnedStr::from_str("Awaiting party").unwrap()));
|
||||
}
|
||||
|
||||
if self.view == ViewState::Results {
|
||||
|
|
@ -255,7 +273,10 @@ impl DeviceState {
|
|||
let question = self.question.as_ref()?;
|
||||
let title_line = if question.text.len() > 16 {
|
||||
// overscroll, should show spaces after the end
|
||||
self.title_offset %= question.text.len() - 31;
|
||||
let scroll_len = question.text.len().saturating_sub(15);
|
||||
if scroll_len > 0 {
|
||||
self.title_offset %= scroll_len;
|
||||
}
|
||||
let end = usize::min(self.title_offset + 16, question.text.len());
|
||||
OwnedStr::from_str(&question.text[self.title_offset..end]).unwrap()
|
||||
} else {
|
||||
|
|
@ -306,8 +327,8 @@ pub enum WriteType<'a> {
|
|||
DeviceId(&'a str),
|
||||
}
|
||||
|
||||
pub fn parse_proxy_output<'a>(input: &'a str) -> Result<ProxyOutput<'a>, serde_json::Error> {
|
||||
serde_json::from_str::<ProxyOutput<'a>>(input)
|
||||
pub fn parse_proxy_output(input: &str) -> Result<ProxyOutput, serde_json::Error> {
|
||||
serde_json::from_str::<ProxyOutput>(input)
|
||||
}
|
||||
|
||||
pub fn serialize_write(data: &WriteType<'_>) -> Result<String, serde_json::Error> {
|
||||
|
|
@ -453,6 +474,67 @@ mod tests {
|
|||
assert!(state.question().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_numeric_question_with_escaped_quotes() {
|
||||
let data = parse_proxy_output(
|
||||
r#"{"Question":{"text":"How many players have \"Porter Robinson\" as a favourite artist?","points":10,"index":2,"q_type":{"Numeric":{"min":0,"max":2}}}}"#,
|
||||
)
|
||||
.unwrap();
|
||||
let mut state = DeviceState::new();
|
||||
|
||||
state.apply_proxy_output(data);
|
||||
|
||||
let question = state.question().unwrap();
|
||||
assert_eq!(question.index, 2);
|
||||
assert_eq!(
|
||||
question.text.as_str(),
|
||||
"How many players have \"Porter Robinson\" as a favourite artist?",
|
||||
);
|
||||
assert_eq!(state.wheel().value, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn preserves_numeric_wheel_for_same_question_updates() {
|
||||
let mut state = DeviceState::new();
|
||||
state.apply_proxy_output(
|
||||
parse_proxy_output(
|
||||
r#"{"Question":{"text":"Q","points":10,"index":2,"q_type":{"Numeric":{"min":0,"max":10}}}}"#,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
state.wheel_mut().value = 7;
|
||||
|
||||
state.apply_proxy_output(
|
||||
parse_proxy_output(
|
||||
r#"{"Question":{"text":"Q updated","points":10,"index":2,"q_type":{"Numeric":{"min":0,"max":10}}}}"#,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
assert_eq!(state.wheel().value, 7);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resets_numeric_wheel_for_new_questions() {
|
||||
let mut state = DeviceState::new();
|
||||
state.apply_proxy_output(
|
||||
parse_proxy_output(
|
||||
r#"{"Question":{"text":"Q","points":10,"index":2,"q_type":{"Numeric":{"min":0,"max":10}}}}"#,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
state.wheel_mut().value = 7;
|
||||
|
||||
state.apply_proxy_output(
|
||||
parse_proxy_output(
|
||||
r#"{"Question":{"text":"Next","points":10,"index":3,"q_type":{"Numeric":{"min":0,"max":10}}}}"#,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
assert_eq!(state.wheel().value, 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_and_renders_waiting_for_party() {
|
||||
let data = parse_proxy_output(r#"{"WaitingForParty":"User"}"#).unwrap();
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ pub async fn tcp_read_loop(
|
|||
};
|
||||
if let Some(last) = str.lines().last() {
|
||||
let Ok(data) = device_state::parse_proxy_output(last) else {
|
||||
println!("parse proxy output failed: {}", last);
|
||||
continue;
|
||||
};
|
||||
let mut state = STATE.lock().await;
|
||||
|
|
|
|||
Loading…
Reference in a new issue