File size: 4,110 Bytes
d0b8e8f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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
}