301 lines
9.9 KiB
Forth
301 lines
9.9 KiB
Forth
module DredgePos.Floorplan.Model
|
|
|
|
open DredgePos.Types
|
|
open System
|
|
open System.IO
|
|
open System.Xml.Linq
|
|
open DredgeFramework
|
|
open Dapper.FSharp
|
|
open Thoth.Json.Net
|
|
let activeTablePath = "tables/active/"
|
|
|
|
let getTableFile (tableNumber: int) =
|
|
let tableNumberString = tableNumber |> string
|
|
activeTablePath + "table" + tableNumberString + ".table"
|
|
|
|
let tableNumberIsOpen (tableNumber: int) =
|
|
let tableFile = getTableFile tableNumber
|
|
File.Exists tableFile
|
|
|
|
let tableIsOpen (table: floorplan_table) = tableNumberIsOpen table.table_number
|
|
|
|
let fileNameToTableNumber (fileName: string) = //Takes a file name for a floorplan table and returns the table number
|
|
if fileName.Contains ".table" then
|
|
let fileName = (fileName.Split ".")[0]
|
|
(fileName.Split "/table")[1] |> int
|
|
else 0
|
|
|
|
let openTables () = //Get a list of all open tables.
|
|
let tableList = Directory.GetFiles(activeTablePath)
|
|
|
|
tableList
|
|
|> Array.map fileNameToTableNumber
|
|
|> Array.filter(fun tableNumber -> tableNumber > 0)
|
|
|
|
let getTableNumber table = table.table_number
|
|
|
|
let tablesInRoom (roomId: int) = //Get a list of all tables in a particular room.
|
|
select {
|
|
table "floorplan_tables"
|
|
where (eq "room_id" roomId)
|
|
}
|
|
|> Database.Select<floorplan_table>
|
|
|
|
|
|
let getActiveTables (venueId: int) =
|
|
select{
|
|
table "floorplan_tables"
|
|
where (eq "venue_id" venueId)
|
|
}
|
|
|> Database.Select
|
|
|> Array.filter tableIsOpen
|
|
|> Array.map (fun table -> table.table_number)
|
|
|
|
let openNewTable tableNumber = //Create a new table file pre-populated with skeleton data
|
|
let tableFile = getTableFile tableNumber
|
|
if not <| File.Exists tableFile then
|
|
let newTableTemplate = $"""
|
|
<table openedby="" number="{tableNumber}"></table>
|
|
"""
|
|
File.Create tableFile |> ignore
|
|
File.WriteAllText (tableFile, newTableTemplate)
|
|
|
|
let transferTable origin destination = //Transfers a table from one to another
|
|
let originFile = getTableFile origin
|
|
let destinationFile = getTableFile destination
|
|
|
|
if tableNumberIsOpen origin then
|
|
(* If the destination is not an already open table,
|
|
then we simply have to rename the origin to destination *)
|
|
if not <| tableNumberIsOpen destination then
|
|
let content = File.ReadAllText originFile
|
|
let newContent = content.Replace($"number=\"{origin|>string}\">", $"number=\"{destination|>string}\">")
|
|
File.WriteAllText(originFile, newContent)
|
|
File.Move(originFile, destinationFile)
|
|
else
|
|
let originXML = XDocument.Load originFile
|
|
let destinationXML = XDocument.Load destinationFile
|
|
destinationXML.Root.Add(originXML.Root.Elements())
|
|
destinationXML.Save destinationFile
|
|
File.Delete originFile
|
|
|
|
let saveOrderToTable orderXML tableNumber =
|
|
let tableFile = getTableFile tableNumber
|
|
let tableXML = tableFile
|
|
|> File.ReadAllText
|
|
|> StringReplace "</table>" (orderXML + "</table>")
|
|
|
|
File.WriteAllText(tableFile, tableXML)
|
|
|
|
let getTableSafely (tableNumber: int) =
|
|
let query = select {
|
|
table "floorplan_tables"
|
|
where (eq "table_number" tableNumber + eq "venue_id" (getCurrentVenue()))
|
|
}
|
|
|
|
query
|
|
|> Database.Select<floorplan_table>
|
|
|> Array.tryItem 0
|
|
|
|
let getTable (tableNumber : int) =
|
|
match getTableSafely tableNumber with
|
|
| None -> failwith $"Table {tableNumber} not found in current venue"
|
|
| Some table -> table
|
|
|
|
let getTableById (id : int) =
|
|
select {
|
|
table "floorplan_tables"
|
|
where (eq "id" id)
|
|
}
|
|
|> Database.Select<floorplan_table>
|
|
|> first
|
|
|
|
let getRoom (roomId: int) =
|
|
select {
|
|
table "rooms"
|
|
where (eq "id" roomId)
|
|
} |> Database.Select<room> |> first
|
|
|
|
let updateTablePosition (floorplanTable: floorplan_table) = Entity.Update floorplanTable
|
|
|
|
let createEmptyReservation (reservation: reservation) =
|
|
update {
|
|
table "floorplan_tables"
|
|
set {| status = 2 |}
|
|
where(eq "id" reservation.floorplan_table_id)
|
|
} |> Database.Update |> ignore
|
|
|
|
Entity.Create reservation
|
|
|
|
let getChildTables tableNumber =
|
|
let table = getTable tableNumber
|
|
let json = table.merged_children
|
|
|
|
let result = json |> Decode.Auto.fromString<floorplan_table[]>
|
|
match result with
|
|
| Ok tables -> tables
|
|
| Error _ -> [||]
|
|
|
|
|
|
let matchTable (tableNumberToMatch: int) (floorplanTableToCheck: floorplan_table) =
|
|
tableNumberToMatch = floorplanTableToCheck.table_number
|
|
|
|
let findChildTable (childTable: int) (parentTable: floorplan_table) =
|
|
let json = parentTable.merged_children
|
|
let childTables = json |> Decode.Auto.fromString<floorplan_table[]>
|
|
|
|
let matchedTables =
|
|
match childTables with
|
|
| Ok table -> table |> Array.map(matchTable childTable)
|
|
| Error _ -> [|false|]
|
|
|> removeFalseValues
|
|
|> length
|
|
|
|
match matchedTables with
|
|
| 0 -> 0
|
|
| _ -> parentTable.table_number
|
|
|
|
let tableExists (tableNumber: int) =
|
|
let numberOfResults =
|
|
select{
|
|
table "floorplan_tables"
|
|
where (eq "table_number" tableNumber + eq "venue_id" (getCurrentVenue()))
|
|
} |> Database.Select<floorplan_table> |> length
|
|
|
|
match numberOfResults with
|
|
| 0 ->
|
|
let allTables =
|
|
Entity.GetAllInVenue<floorplan_table>
|
|
|> Array.map(findChildTable tableNumber)
|
|
|> Array.filter(fun tableNumber -> tableNumber <> 0)
|
|
|
|
|
|
match allTables.Length with
|
|
| 0 -> false |> string //Table does not exist
|
|
| _ ->
|
|
let parentTableData = getTable allTables[0]
|
|
let parentRoom = getRoom parentTableData.room_id
|
|
let parentRoomName = parentRoom.name
|
|
language.getAndReplace "error_table_exists_merged" [parentRoomName; parentTableData.table_number.ToString()]
|
|
|
|
|
|
| _ ->
|
|
let tableData = getTable tableNumber
|
|
let room = getRoom tableData.room_id
|
|
language.getAndReplace "error_table_exists" [room.name]
|
|
|
|
|
|
let addNewTableWithoutOutput (newTable: floorplan_table) =
|
|
insert{
|
|
table "floorplan_tables"
|
|
value newTable
|
|
}
|
|
|> Database.Insert
|
|
|
|
let addNewTable (newTable: floorplan_table) = Entity.Create newTable
|
|
|
|
let mergeTables parent child = //Merge two tables together
|
|
if parent = child then false else
|
|
let parentTable = getTable parent
|
|
let childTable = getTable child
|
|
|
|
let xDiff = (parentTable.pos_x - childTable.pos_x) |> Math.Abs
|
|
let yDiff = (parentTable.pos_y - childTable.pos_y) |> Math.Abs
|
|
|
|
let newHeight =
|
|
if xDiff < yDiff then parentTable.height + childTable.height
|
|
else parentTable.height
|
|
|
|
let newWidth =
|
|
if xDiff >= yDiff then parentTable.width + childTable.width
|
|
else parentTable.width
|
|
|
|
let newPosX =
|
|
if parentTable.pos_x <= childTable.pos_x then parentTable.pos_x + xDiff/2
|
|
else parentTable.pos_x - xDiff/2
|
|
|
|
let newPosY =
|
|
if parentTable.pos_y <= childTable.pos_y then parentTable.pos_y + yDiff/2
|
|
else parentTable.pos_y - yDiff/2
|
|
|
|
let newChildTable = childTable
|
|
|
|
let existingChildrenJson = parentTable.merged_children |> StringTrim
|
|
let existingChildren =
|
|
existingChildrenJson |> Decode.Auto.fromString<floorplan_table[]>
|
|
|
|
let tableList =
|
|
match existingChildren with
|
|
| Error _ -> [|newChildTable|]
|
|
| Ok tables -> [tables ; [|newChildTable|]] |> Array.concat
|
|
|
|
let newChildrenJson = tableList |> jsonEncode
|
|
let parentPreviousState = parentTable |> jsonEncode
|
|
|
|
update {
|
|
table "floorplan_tables"
|
|
set {|
|
|
merged_children = newChildrenJson
|
|
previous_state = parentPreviousState
|
|
height = newHeight
|
|
width = newWidth
|
|
pos_x = newPosX
|
|
pos_y = newPosY
|
|
default_covers = parentTable.default_covers + childTable.default_covers
|
|
|}
|
|
where (eq "table_number" parent + eq "venue_id" (getCurrentVenue()))
|
|
} |> Database.Update |> ignore
|
|
|
|
Entity.DeleteById<floorplan_table> newChildTable.id
|
|
|> ignore
|
|
|
|
true
|
|
|
|
|
|
let updateUnmergedTables parentTable childTable =
|
|
update {
|
|
table "floorplan_tables"
|
|
set parentTable
|
|
where(eq "table_number" parentTable.table_number + eq "venue_id" (getCurrentVenue()))
|
|
} |> Database.Update |> ignore
|
|
|
|
addNewTableWithoutOutput childTable |> ignore
|
|
true
|
|
|
|
let processUnmerge originalTable unmergedChild =
|
|
let previousState = originalTable.previous_state |> Decode.Auto.fromString<floorplan_table>
|
|
|
|
match previousState with
|
|
| Ok table -> updateUnmergedTables table unmergedChild
|
|
| Error _ -> false
|
|
|
|
let unmergeTable tableNumber = //Separates a merged table into itself and the last table merged into it.
|
|
let currentTable = getTable tableNumber
|
|
let mergedChildren = currentTable.merged_children |> Decode.Auto.fromString<floorplan_table[]>
|
|
|
|
match mergedChildren with
|
|
| Ok listOfChildTables ->
|
|
let unmergedChild = listOfChildTables |> last
|
|
processUnmerge currentTable unmergedChild |> ignore
|
|
Some (getTable currentTable.table_number, unmergedChild)
|
|
| Error _ -> None
|
|
|
|
|
|
|
|
let getReservationList (tableList: floorplan_table[]) =
|
|
tableList |> Array.collect Entity.GetAllRelated<reservation, floorplan_table>
|
|
|
|
let newReservation name time covers =
|
|
let reservation = {
|
|
id = 0
|
|
name = name
|
|
time = time
|
|
covers = covers
|
|
floorplan_table_id = 0
|
|
created_at = CurrentTime()
|
|
}
|
|
|
|
Entity.Create reservation
|
|
|
|
|
|
let tableList () = Entity.GetAllInVenue<floorplan_table> |