You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lean4game/server/GameServer/Game.lean

160 lines
5.0 KiB
Plaintext

import GameServer.RpcHandlers
open Lean
2 years ago
structure GameServerState :=
(env : Lean.Environment)
2 years ago
(game : Name)
(gameDir : String)
2 years ago
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
2 years ago
open IO
def getGame (game : Name): GameServerM Json := do
2 years ago
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
2 years ago
/--
Fields:
- description: Lemma in mathematical language.
- descriptionGoal: Lemma printed as Lean-Code.
-/
2 years ago
structure LevelInfo where
index : Nat
title : String
tactics : Array ComputedInventoryItem
lemmas : Array ComputedInventoryItem
definitions : Array ComputedInventoryItem
introduction : String
conclusion : String
descrText : Option String := none
descrFormat : String := ""
lemmaTab : Option String
statementName : Option String
deriving ToJson, FromJson
2 years ago
structure LoadLevelParams where
2 years ago
world : Name
level : Nat
deriving ToJson, FromJson
structure DidOpenLevelParams where
uri : String
gameDir : String
levelModule : Name
tactics : Array ComputedInventoryItem
lemmas : Array ComputedInventoryItem
definitions : Array ComputedInventoryItem
deriving ToJson, FromJson
structure LoadDocParams where
name : Name
type : InventoryType
deriving ToJson, FromJson
def handleDidOpenLevel (params : Json) : GameServerM Unit := do
let p ← parseParams _ params
let m := p.textDocument
-- Execute the regular handling of the `didOpen` event
handleDidOpen p
let fw ← findFileWorker! m.uri
-- let s ← get
let c ← read
let some lvl ← GameServer.getLevelByFileName? c.initParams ((System.Uri.fileUriToPath? m.uri).getD m.uri |>.toString)
| do
c.hLog.putStr s!"Level not found: {m.uri} {c.initParams.rootUri?}"
c.hLog.flush
-- Send an extra notification to the file worker to inform it about the level data
fw.stdin.writeLspNotification {
method := "$/game/didOpenLevel"
param := {
uri := m.uri
gameDir := (← get).gameDir
levelModule := lvl.module
tactics := lvl.tactics.computed
lemmas := lvl.lemmas.computed
2 years ago
definitions := lvl.definitions.computed
: DidOpenLevelParams
}
}
2 years ago
partial def handleServerEvent (ev : ServerEvent) : GameServerM Bool := do
match ev with
| ServerEvent.clientMsg msg =>
match msg with
| Message.request id "info" _ =>
2 years ago
let s ← get
let c ← read
2 years ago
c.hOut.writeLspResponse ⟨id, (← getGame s.game)⟩
2 years ago
return true
| Message.request id "loadLevel" params =>
let p ← parseParams LoadLevelParams (toJson params)
2 years ago
let s ← get
let c ← read
2 years ago
let some lvl ← getLevel? {game := s.game, world := p.world, level := p.level}
2 years ago
| do
c.hOut.writeLspResponseError ⟨id, .invalidParams, s!"Level not found: world {p.world}, level {p.level}", none⟩
return true
let env ← getEnv
2 years ago
let levelInfo : LevelInfo :=
{ index := lvl.index,
title := lvl.title,
tactics := lvl.tactics.computed,
lemmas := lvl.lemmas.computed,
2 years ago
definitions := lvl.definitions.computed,
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
conclusion := lvl.conclusion
lemmaTab := lvl.lemmaTab
statementName := match lvl.statementName with
| .anonymous => none
| name => match (inventoryDocExt.getState env).find?
(fun x => x.name == name && x.type == .Lemma) with
| some n => n.displayName
| none => name.toString
-- Note: we could call `.find!` because we check in `Statement` that the
-- lemma doc must exist.
}
2 years ago
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 ← getInventoryDoc? p.name p.type
| do
c.hOut.writeLspResponseError ⟨id, .invalidParams, s!"Documentation not found: {p.name}", none⟩
return true
let doc : Doc :=
{ name := doc.name.toString
displayName := doc.displayName
text := doc.content }
c.hOut.writeLspResponse ⟨id, ToJson.toJson doc⟩
return true
| _ => return false
| _ => return false
end Game