import Lean import GameServer.EnvExtensions open Lean structure GameServerState := (env : Lean.Environment) (game : Name) abbrev GameServerM := StateT GameServerState Server.Watchdog.ServerM instance : MonadEnv GameServerM := { getEnv := do return (← get).env modifyEnv := fun f => do let s ← get set {s with env := f s.env} } namespace Game open Server open Watchdog open Lsp open JsonRpc open IO def getGame (game : Name): GameServerM Json := do let some game ← getGame? game | throwServerError "Game not found" let gameJson : Json := toJson game -- Add world sizes to Json object let worldSize := game.worlds.nodes.toList.map (fun (n, w) => (n.toString, w.levels.size)) let gameJson := gameJson.mergeObj (Json.mkObj [("worldSize", Json.mkObj worldSize)]) return gameJson /-- Fields: - description: Lemma in mathematical language. - descriptionGoal: Lemma printed as Lean-Code. -/ structure LevelInfo where index : Nat title : String tactics: Array Availability lemmas: Array Availability introduction : String descrText : String := "" descrFormat : String := "" deriving ToJson structure LoadLevelParams where world : Name level : Nat deriving ToJson, FromJson structure Doc where name: String text: String deriving ToJson inductive TacOrLem := | tactic | «lemma» deriving ToJson, FromJson structure LoadDocParams where name : Name type : TacOrLem deriving ToJson, FromJson def mkDoc (name : Name) (type : TacOrLem) : GameServerM (Option Doc) := do match type with | .tactic => do let doc ← getTacticDoc? name return doc.map fun doc => { name := doc.name.toString text := doc.content } | .lemma => do let doc ← getLemmaDoc? name return doc.map fun doc => { name := doc.name.toString text := doc.content } partial def handleServerEvent (ev : ServerEvent) : GameServerM Bool := do match ev with | ServerEvent.clientMsg msg => match msg with | Message.request id "info" _ => let s ← get let c ← read c.hOut.writeLspResponse ⟨id, (← getGame s.game)⟩ return true | Message.request id "loadLevel" params => let p ← parseParams LoadLevelParams (toJson params) let s ← get let c ← read let some lvl ← getLevel? {game := s.game, world := p.world, level := p.level} | do c.hOut.writeLspResponseError ⟨id, .invalidParams, s!"Level not found: world {p.world}, level {p.level}", none⟩ return true let levelInfo : LevelInfo := { index := lvl.index, title := lvl.title, tactics := lvl.tactics, lemmas := lvl.lemmas, descrText := lvl.descrText, descrFormat := lvl.descrFormat --toExpr <| format (lvl.goal.raw) --toString <| Syntax.formatStx (lvl.goal.raw) --Syntax.formatStx (lvl.goal.raw) , -- TODO introduction := lvl.introduction } c.hOut.writeLspResponse ⟨id, ToJson.toJson levelInfo⟩ return true | Message.request id "loadDoc" params => let p ← parseParams LoadDocParams (toJson params) let s ← get let c ← read let some doc ← mkDoc p.name p.type | do c.hOut.writeLspResponseError ⟨id, .invalidParams, s!"Documentation not found: {p.name}", none⟩ return true c.hOut.writeLspResponse ⟨id, ToJson.toJson doc⟩ return true | _ => return false | _ => return false end Game