aboutsummaryrefslogtreecommitdiff
path: root/Sources/LichessClient/LichessClient+Tablebase.swift
blob: a06c1c7a0fa65658c596a28d09adcafa43ef8455 (plain)
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//
//  LichessClient+Tablebase.swift
//
//
//  Created by Navan Chauhan on 4/23/24.
//

import Foundation

extension LichessClient {
  public struct TablebaseLookup: Codable {
    public let dtz: Int?
    public let precise_dtz: Int?
    public let dtm: Int?
    public let checkmate: Bool?
    public let stalemate: Bool?
    public let variant_win: Bool?
    public let variant_loss: Bool?
    public let insufficient_material: Bool?
    public let category: TablebaseCategory?
    public var moves: [TablebaseMove]?
  }

  public struct TablebaseMove: Codable {
    public let uci: String?
    public let san: String?
    public let dtz: Int?
    public let precise_dtz: Int?
    public let dtm: Int?
    public let zeroing: Bool?
    public let checkmate: Bool?
    public let stalemate: Bool?
    public let variant_win: Bool?
    public let variant_loss: Bool?
    public let insufficient_material: Bool?
    public let category: TablebaseCategory?
  }

  public enum TablebaseCategory: Codable {
    case win
    case unknown
    case maybe_hyphen_win
    case cursed_hyphen_win
    case draw
    case blessed_hyphen_loss
    case maybe_hyphen_loss
    case loss
  }

  func convertCategoryTablebaseJson(payload: Components.Schemas.TablebaseJson.categoryPayload?)
    -> TablebaseCategory?
  {
    guard let payload = payload else { return nil }
    switch payload {
    case .win:
      return .win
    case .unknown:
      return .unknown
    case .maybe_hyphen_win:
      return .maybe_hyphen_win
    case .cursed_hyphen_win:
      return .cursed_hyphen_win
    case .draw:
      return .draw
    case .blessed_hyphen_loss:
      return .blessed_hyphen_loss
    case .maybe_hyphen_loss:
      return .maybe_hyphen_loss
    case .loss:
      return .loss
    }
  }

  func convertCategoryTablebaseJsonMoves(payload: Components.Schemas.Move.categoryPayload?)
    -> TablebaseCategory?
  {
    guard let payload = payload else { return nil }
    switch payload {
    case .win:
      return .win
    case .unknown:
      return .unknown
    case .maybe_hyphen_win:
      return .maybe_hyphen_win
    case .cursed_hyphen_win:
      return .cursed_hyphen_win
    case .draw:
      return .draw
    case .blessed_hyphen_loss:
      return .blessed_hyphen_loss
    case .maybe_hyphen_loss:
      return .maybe_hyphen_loss
    case .loss:
      return .loss
    }
  }

  public func getStandardTablebase(fen: String) async throws -> TablebaseLookup {
    let response = try await underlyingTablebaseClient.tablebaseStandard(query: .init(fen: fen))
    switch response {
    case .ok(let okResponse):
      switch okResponse.body {
      case .json(let tablebaseJson):
        var tablebaseLookup = TablebaseLookup(
          dtz: tablebaseJson.dtz, precise_dtz: tablebaseJson.precise_dtz, dtm: tablebaseJson.dtm,
          checkmate: tablebaseJson.checkmate, stalemate: tablebaseJson.stalemate,
          variant_win: tablebaseJson.variant_win, variant_loss: tablebaseJson.variant_win,
          insufficient_material: tablebaseJson.insufficient_material,
          category: convertCategoryTablebaseJson(payload: tablebaseJson.category), moves: [])

        guard let moves = tablebaseJson.moves else {
          return tablebaseLookup
        }
        var tablebaseMoves: [TablebaseMove] = []
        for move in moves {
          let tablebaseMove = TablebaseMove(
            uci: move.uci, san: move.san, dtz: move.dtz, precise_dtz: move.precise_dtz,
            dtm: move.dtm, zeroing: move.zeroing, checkmate: move.checkmate,
            stalemate: move.stalemate, variant_win: move.variant_win,
            variant_loss: move.variant_loss, insufficient_material: move.insufficient_material,
            category: convertCategoryTablebaseJsonMoves(payload: move.category))
          tablebaseMoves.append(tablebaseMove)
        }
        tablebaseLookup.moves = tablebaseMoves
        return tablebaseLookup

      }
    case .undocumented(let statusCode, _):
      throw LichessClientError.undocumentedResponse(statusCode: statusCode)
    }
  }

  public func getAtomicTablebase(fen: String) {
    fatalError("getAtomicTablebase(fen: String) has not been implemented yet. Please file an issue")
  }

  public func getAntichessTablebase(fen: String) {
    fatalError(
      "getAntichessTablebase(fen: String) has not been implemented yet. Please file an issue")
  }

}