| import gleam/list |
| import gleam/option.{type Option, None} |
| import gleam/int |
| import gleam/float |
|
|
| pub type StudySession { |
| StudySession(room_id: String, room_name: String, participants: List(Participant), created_at: String, max_participants: Int, focus_orbs: List(FocusOrb)) |
| } |
|
|
| pub type Participant { |
| Participant(user_id: String, username: String, focus_level: Float, cards_studied: Int, current_card: Option(String), is_active: Bool, joined_at: String) |
| } |
|
|
| pub type FocusOrb { |
| FocusOrb(user_id: String, x: Float, y: Float, brightness: Float, color: String, label: String) |
| } |
|
|
| pub type MultiplayerMessage { |
| JoinRoom(user_id: String, username: String) |
| LeaveRoom(user_id: String) |
| UpdateFocusLevel(user_id: String, level: Float) |
| UpdatePosition(user_id: String, x: Float, y: Float) |
| CardCompleted(user_id: String, card_id: String) |
| ChatMessage(user_id: String, message: String, timestamp: String) |
| SyncState(session_state: StudySession) |
| } |
|
|
| pub fn create_session(room_id: String, room_name: String) -> StudySession { |
| StudySession(room_id: room_id, room_name: room_name, participants: [], created_at: "2026-03-19T00:00:00Z", max_participants: 10, focus_orbs: []) |
| } |
|
|
| pub fn add_participant(session: StudySession, user_id: String, username: String) -> StudySession { |
| let count = list.length(session.participants) |
| case count >= session.max_participants { |
| True -> session |
| False -> { |
| let p = Participant(user_id: user_id, username: username, focus_level: 100.0, cards_studied: 0, current_card: None, is_active: True, joined_at: "2026-03-19T00:00:00Z") |
| StudySession(..session, participants: [p, ..session.participants]) |
| } |
| } |
| } |
|
|
| pub fn remove_participant(session: StudySession, user_id: String) -> StudySession { |
| let filtered = list.filter(session.participants, fn(p) { p.user_id != user_id }) |
| StudySession(..session, participants: filtered) |
| } |
|
|
| pub fn update_focus_orb(session: StudySession, user_id: String, x: Float, y: Float, brightness: Float) -> StudySession { |
| let new_orb = FocusOrb(user_id: user_id, x: x, y: y, brightness: brightness, color: "#00f2ff", label: user_id) |
| let filtered_orbs = list.filter(session.focus_orbs, fn(o) { o.user_id != user_id }) |
| StudySession(..session, focus_orbs: [new_orb, ..filtered_orbs]) |
| } |
|
|
| pub fn broadcast_message(session: StudySession, message: String) -> String { |
| "Broadcasting to " <> int.to_string(list.length(session.participants)) <> " participants: " <> message |
| } |
|
|
| pub fn serialize_session_state(session: StudySession) -> String { |
| "{\"room_id\":\"" <> session.room_id <> "\",\"participants\":" <> int.to_string(list.length(session.participants)) <> ",\"focus_orbs\":" <> int.to_string(list.length(session.focus_orbs)) <> "}" |
| } |
|
|
| pub fn generate_svg_focus_space(session: StudySession) -> String { |
| let header = "<svg width='800' height='600' class='focus-space'>" |
| let orbs = list.fold(session.focus_orbs, "", fn(acc, orb) { |
| acc <> "<circle cx='" <> float.to_string(orb.x) <> "' cy='" <> float.to_string(orb.y) <> "' r='30' fill='" <> orb.color <> "' />" |
| }) |
| header <> orbs <> "</svg>" |
| } |
|
|
| pub fn calculate_group_focus_score(session: StudySession) -> Float { |
| case list.length(session.participants) { |
| 0 -> 0.0 |
| n -> list.fold(session.participants, 0.0, fn(acc, p) { acc +. p.focus_level }) /. int.to_float(n) |
| } |
| } |
|
|
| pub fn detect_focus_dip(current: Float, previous: Float) -> Bool { |
| current <. previous *. 0.8 |
| } |
|
|
| pub fn send_focus_alert(_user_id: String, username: String) -> String { |
| "Alert for " <> username <> ": Focus dropping" |
| } |
|
|
| pub fn track_study_velocity(session: StudySession) -> String { |
| let total = list.fold(session.participants, 0, fn(acc, p) { acc + p.cards_studied }) |
| "Cards studied: " <> int.to_string(total) |
| } |
|
|
| pub fn generate_collaboration_report(session: StudySession) -> String { |
| "<div><h3>" <> session.room_name <> "</h3><p>" <> int.to_string(list.length(session.participants)) <> " participants</p></div>" |
| } |
|
|
| pub fn list_active_rooms() -> List(StudySession) { |
| [] |
| } |
|
|
| pub fn invite_participant(_session: StudySession, invitee: String) -> String { |
| "Invited " <> invitee |
| } |
|
|
|
|