Files
galaxy-game/pkg/transcoder/report.go
T
2026-03-31 19:16:34 +02:00

1395 lines
47 KiB
Go

package transcoder
import (
"encoding/binary"
"errors"
"fmt"
"sort"
model "galaxy/model/report"
fbs "galaxy/schema/fbs/report"
flatbuffers "github.com/google/flatbuffers/go"
"github.com/google/uuid"
)
// ReportToPayload converts model.Report from the internal representation to
// FlatBuffers bytes that can be sent over network transports.
//
// The function returns an error when the input is nil.
func ReportToPayload(report *model.Report) ([]byte, error) {
if report == nil {
return nil, errors.New("encode report payload: report is nil")
}
builder := flatbuffers.NewBuilder(4096)
race := builder.CreateString(report.Race)
voteFor := builder.CreateString(report.VoteFor)
playerOffsets := make([]flatbuffers.UOffsetT, len(report.Player))
for i := range report.Player {
playerOffsets[i] = encodeReportPlayer(builder, &report.Player[i])
}
localScienceOffsets := make([]flatbuffers.UOffsetT, len(report.LocalScience))
for i := range report.LocalScience {
localScienceOffsets[i] = encodeReportScience(builder, &report.LocalScience[i])
}
otherScienceOffsets := make([]flatbuffers.UOffsetT, len(report.OtherScience))
for i := range report.OtherScience {
otherScienceOffsets[i] = encodeReportOtherScience(builder, &report.OtherScience[i])
}
localShipClassOffsets := make([]flatbuffers.UOffsetT, len(report.LocalShipClass))
for i := range report.LocalShipClass {
localShipClassOffsets[i] = encodeReportShipClass(builder, &report.LocalShipClass[i])
}
otherShipClassOffsets := make([]flatbuffers.UOffsetT, len(report.OtherShipClass))
for i := range report.OtherShipClass {
otherShipClassOffsets[i] = encodeReportOthersShipClass(builder, &report.OtherShipClass[i])
}
bombingOffsets := make([]flatbuffers.UOffsetT, len(report.Bombing))
for i := range report.Bombing {
if report.Bombing[i] == nil {
return nil, fmt.Errorf("encode report bombing %d: bombing is nil", i)
}
bombingOffsets[i] = encodeReportBombing(builder, report.Bombing[i])
}
incomingGroupOffsets := make([]flatbuffers.UOffsetT, len(report.IncomingGroup))
for i := range report.IncomingGroup {
incomingGroupOffsets[i] = encodeReportIncomingGroup(builder, &report.IncomingGroup[i])
}
localPlanetOffsets := make([]flatbuffers.UOffsetT, len(report.LocalPlanet))
for i := range report.LocalPlanet {
localPlanetOffsets[i] = encodeReportLocalPlanet(builder, &report.LocalPlanet[i])
}
shipProductionOffsets := make([]flatbuffers.UOffsetT, len(report.ShipProduction))
for i := range report.ShipProduction {
shipProductionOffsets[i] = encodeReportShipProduction(builder, &report.ShipProduction[i])
}
routeOffsets := make([]flatbuffers.UOffsetT, len(report.Route))
for i := range report.Route {
routeOffsets[i] = encodeReportRoute(builder, &report.Route[i])
}
otherPlanetOffsets := make([]flatbuffers.UOffsetT, len(report.OtherPlanet))
for i := range report.OtherPlanet {
otherPlanetOffsets[i] = encodeReportOtherPlanet(builder, &report.OtherPlanet[i])
}
uninhabitedPlanetOffsets := make([]flatbuffers.UOffsetT, len(report.UninhabitedPlanet))
for i := range report.UninhabitedPlanet {
uninhabitedPlanetOffsets[i] = encodeReportUninhabitedPlanet(builder, &report.UninhabitedPlanet[i])
}
unidentifiedPlanetOffsets := make([]flatbuffers.UOffsetT, len(report.UnidentifiedPlanet))
for i := range report.UnidentifiedPlanet {
unidentifiedPlanetOffsets[i] = encodeReportUnidentifiedPlanet(builder, &report.UnidentifiedPlanet[i])
}
localFleetOffsets := make([]flatbuffers.UOffsetT, len(report.LocalFleet))
for i := range report.LocalFleet {
localFleetOffsets[i] = encodeReportLocalFleet(builder, &report.LocalFleet[i])
}
localGroupOffsets := make([]flatbuffers.UOffsetT, len(report.LocalGroup))
for i := range report.LocalGroup {
localGroupOffsets[i] = encodeReportLocalGroup(builder, &report.LocalGroup[i])
}
otherGroupOffsets := make([]flatbuffers.UOffsetT, len(report.OtherGroup))
for i := range report.OtherGroup {
otherGroupOffsets[i] = encodeReportOtherGroup(builder, &report.OtherGroup[i])
}
unidentifiedGroupOffsets := make([]flatbuffers.UOffsetT, len(report.UnidentifiedGroup))
for i := range report.UnidentifiedGroup {
unidentifiedGroupOffsets[i] = encodeReportUnidentifiedGroup(builder, &report.UnidentifiedGroup[i])
}
playerVector := encodeReportOffsetVector(builder, len(playerOffsets), fbs.ReportStartPlayerVector, playerOffsets)
localScienceVector := encodeReportOffsetVector(builder, len(localScienceOffsets), fbs.ReportStartLocalScienceVector, localScienceOffsets)
otherScienceVector := encodeReportOffsetVector(builder, len(otherScienceOffsets), fbs.ReportStartOtherScienceVector, otherScienceOffsets)
localShipClassVector := encodeReportOffsetVector(builder, len(localShipClassOffsets), fbs.ReportStartLocalShipClassVector, localShipClassOffsets)
otherShipClassVector := encodeReportOffsetVector(builder, len(otherShipClassOffsets), fbs.ReportStartOtherShipClassVector, otherShipClassOffsets)
battleVector := encodeReportUUIDVector(builder, report.Battle)
bombingVector := encodeReportOffsetVector(builder, len(bombingOffsets), fbs.ReportStartBombingVector, bombingOffsets)
incomingGroupVector := encodeReportOffsetVector(builder, len(incomingGroupOffsets), fbs.ReportStartIncomingGroupVector, incomingGroupOffsets)
localPlanetVector := encodeReportOffsetVector(builder, len(localPlanetOffsets), fbs.ReportStartLocalPlanetVector, localPlanetOffsets)
shipProductionVector := encodeReportOffsetVector(builder, len(shipProductionOffsets), fbs.ReportStartShipProductionVector, shipProductionOffsets)
routeVector := encodeReportOffsetVector(builder, len(routeOffsets), fbs.ReportStartRouteVector, routeOffsets)
otherPlanetVector := encodeReportOffsetVector(builder, len(otherPlanetOffsets), fbs.ReportStartOtherPlanetVector, otherPlanetOffsets)
uninhabitedPlanetVector := encodeReportOffsetVector(builder, len(uninhabitedPlanetOffsets), fbs.ReportStartUninhabitedPlanetVector, uninhabitedPlanetOffsets)
unidentifiedPlanetVector := encodeReportOffsetVector(builder, len(unidentifiedPlanetOffsets), fbs.ReportStartUnidentifiedPlanetVector, unidentifiedPlanetOffsets)
localFleetVector := encodeReportOffsetVector(builder, len(localFleetOffsets), fbs.ReportStartLocalFleetVector, localFleetOffsets)
localGroupVector := encodeReportOffsetVector(builder, len(localGroupOffsets), fbs.ReportStartLocalGroupVector, localGroupOffsets)
otherGroupVector := encodeReportOffsetVector(builder, len(otherGroupOffsets), fbs.ReportStartOtherGroupVector, otherGroupOffsets)
unidentifiedGroupVector := encodeReportOffsetVector(builder, len(unidentifiedGroupOffsets), fbs.ReportStartUnidentifiedGroupVector, unidentifiedGroupOffsets)
fbs.ReportStart(builder)
fbs.ReportAddVersion(builder, uint64(report.Version))
fbs.ReportAddTurn(builder, uint64(report.Turn))
fbs.ReportAddWidth(builder, report.Width)
fbs.ReportAddHeight(builder, report.Height)
fbs.ReportAddPlanetCount(builder, report.PlanetCount)
fbs.ReportAddRace(builder, race)
fbs.ReportAddVotes(builder, reportFloatToFBS(report.Votes))
fbs.ReportAddVoteFor(builder, voteFor)
if len(playerOffsets) > 0 {
fbs.ReportAddPlayer(builder, playerVector)
}
if len(localScienceOffsets) > 0 {
fbs.ReportAddLocalScience(builder, localScienceVector)
}
if len(otherScienceOffsets) > 0 {
fbs.ReportAddOtherScience(builder, otherScienceVector)
}
if len(localShipClassOffsets) > 0 {
fbs.ReportAddLocalShipClass(builder, localShipClassVector)
}
if len(otherShipClassOffsets) > 0 {
fbs.ReportAddOtherShipClass(builder, otherShipClassVector)
}
if len(report.Battle) > 0 {
fbs.ReportAddBattle(builder, battleVector)
}
if len(bombingOffsets) > 0 {
fbs.ReportAddBombing(builder, bombingVector)
}
if len(incomingGroupOffsets) > 0 {
fbs.ReportAddIncomingGroup(builder, incomingGroupVector)
}
if len(localPlanetOffsets) > 0 {
fbs.ReportAddLocalPlanet(builder, localPlanetVector)
}
if len(shipProductionOffsets) > 0 {
fbs.ReportAddShipProduction(builder, shipProductionVector)
}
if len(routeOffsets) > 0 {
fbs.ReportAddRoute(builder, routeVector)
}
if len(otherPlanetOffsets) > 0 {
fbs.ReportAddOtherPlanet(builder, otherPlanetVector)
}
if len(uninhabitedPlanetOffsets) > 0 {
fbs.ReportAddUninhabitedPlanet(builder, uninhabitedPlanetVector)
}
if len(unidentifiedPlanetOffsets) > 0 {
fbs.ReportAddUnidentifiedPlanet(builder, unidentifiedPlanetVector)
}
if len(localFleetOffsets) > 0 {
fbs.ReportAddLocalFleet(builder, localFleetVector)
}
if len(localGroupOffsets) > 0 {
fbs.ReportAddLocalGroup(builder, localGroupVector)
}
if len(otherGroupOffsets) > 0 {
fbs.ReportAddOtherGroup(builder, otherGroupVector)
}
if len(unidentifiedGroupOffsets) > 0 {
fbs.ReportAddUnidentifiedGroup(builder, unidentifiedGroupVector)
}
reportOffset := fbs.ReportEnd(builder)
fbs.FinishReportBuffer(builder, reportOffset)
return builder.FinishedBytes(), nil
}
// PayloadToReport converts FlatBuffers payload bytes into model.Report.
//
// The function validates payload structure and integer conversions.
// Malformed payloads are returned as errors.
func PayloadToReport(data []byte) (result *model.Report, err error) {
if len(data) == 0 {
return nil, errors.New("decode report payload: data is empty")
}
defer func() {
if recovered := recover(); recovered != nil {
result = nil
err = fmt.Errorf("decode report payload: panic recovered: %v", recovered)
}
}()
flatReport := fbs.GetRootAsReport(data, 0)
version, err := uint64ToUint(flatReport.Version(), "version")
if err != nil {
return nil, fmt.Errorf("decode report payload: %w", err)
}
turn, err := uint64ToUint(flatReport.Turn(), "turn")
if err != nil {
return nil, fmt.Errorf("decode report payload: %w", err)
}
result = &model.Report{
Version: version,
Turn: turn,
Width: flatReport.Width(),
Height: flatReport.Height(),
PlanetCount: flatReport.PlanetCount(),
Race: string(flatReport.Race()),
Votes: reportFloatFromFBS(flatReport.Votes()),
VoteFor: string(flatReport.VoteFor()),
}
if err := decodeReportPlayerVector(flatReport, result); err != nil {
return nil, err
}
if err := decodeReportLocalScienceVector(flatReport, result); err != nil {
return nil, err
}
if err := decodeReportOtherScienceVector(flatReport, result); err != nil {
return nil, err
}
if err := decodeReportLocalShipClassVector(flatReport, result); err != nil {
return nil, err
}
if err := decodeReportOtherShipClassVector(flatReport, result); err != nil {
return nil, err
}
if err := decodeReportBattleVector(flatReport, result); err != nil {
return nil, err
}
if err := decodeReportBombingVector(flatReport, result); err != nil {
return nil, err
}
if err := decodeReportIncomingGroupVector(flatReport, result); err != nil {
return nil, err
}
if err := decodeReportLocalPlanetVector(flatReport, result); err != nil {
return nil, err
}
if err := decodeReportShipProductionVector(flatReport, result); err != nil {
return nil, err
}
if err := decodeReportRouteVector(flatReport, result); err != nil {
return nil, err
}
if err := decodeReportOtherPlanetVector(flatReport, result); err != nil {
return nil, err
}
if err := decodeReportUninhabitedPlanetVector(flatReport, result); err != nil {
return nil, err
}
if err := decodeReportUnidentifiedPlanetVector(flatReport, result); err != nil {
return nil, err
}
if err := decodeReportLocalFleetVector(flatReport, result); err != nil {
return nil, err
}
if err := decodeReportLocalGroupVector(flatReport, result); err != nil {
return nil, err
}
if err := decodeReportOtherGroupVector(flatReport, result); err != nil {
return nil, err
}
if err := decodeReportUnidentifiedGroupVector(flatReport, result); err != nil {
return nil, err
}
return result, nil
}
func encodeReportPlayer(builder *flatbuffers.Builder, player *model.Player) flatbuffers.UOffsetT {
name := builder.CreateString(player.Name)
relation := builder.CreateString(player.Relation)
fbs.PlayerStart(builder)
fbs.PlayerAddName(builder, name)
fbs.PlayerAddDrive(builder, reportFloatToFBS(player.Drive))
fbs.PlayerAddWeapons(builder, reportFloatToFBS(player.Weapons))
fbs.PlayerAddShields(builder, reportFloatToFBS(player.Shields))
fbs.PlayerAddCargo(builder, reportFloatToFBS(player.Cargo))
fbs.PlayerAddPopulation(builder, reportFloatToFBS(player.Population))
fbs.PlayerAddIndustry(builder, reportFloatToFBS(player.Industry))
fbs.PlayerAddPlanets(builder, player.Planets)
fbs.PlayerAddRelation(builder, relation)
fbs.PlayerAddVotes(builder, reportFloatToFBS(player.Votes))
fbs.PlayerAddExtinct(builder, player.Extinct)
return fbs.PlayerEnd(builder)
}
func encodeReportScience(builder *flatbuffers.Builder, science *model.Science) flatbuffers.UOffsetT {
name := builder.CreateString(science.Name)
fbs.ScienceStart(builder)
fbs.ScienceAddName(builder, name)
fbs.ScienceAddDrive(builder, reportFloatToFBS(science.Drive))
fbs.ScienceAddWeapons(builder, reportFloatToFBS(science.Weapons))
fbs.ScienceAddShields(builder, reportFloatToFBS(science.Shields))
fbs.ScienceAddCargo(builder, reportFloatToFBS(science.Cargo))
return fbs.ScienceEnd(builder)
}
func encodeReportOtherScience(builder *flatbuffers.Builder, science *model.OtherScience) flatbuffers.UOffsetT {
race := builder.CreateString(science.Race)
name := builder.CreateString(science.Name)
fbs.OtherScienceStart(builder)
fbs.OtherScienceAddRace(builder, race)
fbs.OtherScienceAddName(builder, name)
fbs.OtherScienceAddDrive(builder, reportFloatToFBS(science.Drive))
fbs.OtherScienceAddWeapons(builder, reportFloatToFBS(science.Weapons))
fbs.OtherScienceAddShields(builder, reportFloatToFBS(science.Shields))
fbs.OtherScienceAddCargo(builder, reportFloatToFBS(science.Cargo))
return fbs.OtherScienceEnd(builder)
}
func encodeReportShipClass(builder *flatbuffers.Builder, shipClass *model.ShipClass) flatbuffers.UOffsetT {
name := builder.CreateString(shipClass.Name)
fbs.ShipClassStart(builder)
fbs.ShipClassAddName(builder, name)
fbs.ShipClassAddDrive(builder, reportFloatToFBS(shipClass.Drive))
fbs.ShipClassAddArmament(builder, uint64(shipClass.Armament))
fbs.ShipClassAddWeapons(builder, reportFloatToFBS(shipClass.Weapons))
fbs.ShipClassAddShields(builder, reportFloatToFBS(shipClass.Shields))
fbs.ShipClassAddCargo(builder, reportFloatToFBS(shipClass.Cargo))
fbs.ShipClassAddMass(builder, reportFloatToFBS(shipClass.Mass))
return fbs.ShipClassEnd(builder)
}
func encodeReportOthersShipClass(builder *flatbuffers.Builder, shipClass *model.OthersShipClass) flatbuffers.UOffsetT {
race := builder.CreateString(shipClass.Race)
name := builder.CreateString(shipClass.Name)
fbs.OthersShipClassStart(builder)
fbs.OthersShipClassAddRace(builder, race)
fbs.OthersShipClassAddName(builder, name)
fbs.OthersShipClassAddDrive(builder, reportFloatToFBS(shipClass.Drive))
fbs.OthersShipClassAddArmament(builder, uint64(shipClass.Armament))
fbs.OthersShipClassAddWeapons(builder, reportFloatToFBS(shipClass.Weapons))
fbs.OthersShipClassAddShields(builder, reportFloatToFBS(shipClass.Shields))
fbs.OthersShipClassAddCargo(builder, reportFloatToFBS(shipClass.Cargo))
fbs.OthersShipClassAddMass(builder, reportFloatToFBS(shipClass.Mass))
return fbs.OthersShipClassEnd(builder)
}
func encodeReportBombing(builder *flatbuffers.Builder, bombing *model.Bombing) flatbuffers.UOffsetT {
planet := builder.CreateString(bombing.Planet)
owner := builder.CreateString(bombing.Owner)
attacker := builder.CreateString(bombing.Attacker)
production := builder.CreateString(bombing.Production)
fbs.BombingStart(builder)
fbs.BombingAddNumber(builder, uint64(bombing.Number))
fbs.BombingAddPlanet(builder, planet)
fbs.BombingAddOwner(builder, owner)
fbs.BombingAddAttacker(builder, attacker)
fbs.BombingAddProduction(builder, production)
fbs.BombingAddIndustry(builder, reportFloatToFBS(bombing.Industry))
fbs.BombingAddPopulation(builder, reportFloatToFBS(bombing.Population))
fbs.BombingAddColonists(builder, reportFloatToFBS(bombing.Colonists))
fbs.BombingAddCapital(builder, reportFloatToFBS(bombing.Capital))
fbs.BombingAddMaterial(builder, reportFloatToFBS(bombing.Material))
fbs.BombingAddAttackPower(builder, reportFloatToFBS(bombing.AttackPower))
fbs.BombingAddWiped(builder, bombing.Wiped)
return fbs.BombingEnd(builder)
}
func encodeReportIncomingGroup(builder *flatbuffers.Builder, group *model.IncomingGroup) flatbuffers.UOffsetT {
fbs.IncomingGroupStart(builder)
fbs.IncomingGroupAddOrigin(builder, uint64(group.Origin))
fbs.IncomingGroupAddDestination(builder, uint64(group.Destination))
fbs.IncomingGroupAddDistance(builder, reportFloatToFBS(group.Distance))
fbs.IncomingGroupAddSpeed(builder, reportFloatToFBS(group.Speed))
fbs.IncomingGroupAddMass(builder, reportFloatToFBS(group.Mass))
return fbs.IncomingGroupEnd(builder)
}
func encodeReportLocalPlanet(builder *flatbuffers.Builder, planet *model.LocalPlanet) flatbuffers.UOffsetT {
name := builder.CreateString(planet.Name)
production := builder.CreateString(planet.Production)
fbs.LocalPlanetStart(builder)
fbs.LocalPlanetAddX(builder, reportFloatToFBS(planet.X))
fbs.LocalPlanetAddY(builder, reportFloatToFBS(planet.Y))
fbs.LocalPlanetAddNumber(builder, uint64(planet.Number))
fbs.LocalPlanetAddSize(builder, reportFloatToFBS(planet.Size))
fbs.LocalPlanetAddName(builder, name)
fbs.LocalPlanetAddResources(builder, reportFloatToFBS(planet.Resources))
fbs.LocalPlanetAddCapital(builder, reportFloatToFBS(planet.Capital))
fbs.LocalPlanetAddMaterial(builder, reportFloatToFBS(planet.Material))
fbs.LocalPlanetAddIndustry(builder, reportFloatToFBS(planet.Industry))
fbs.LocalPlanetAddPopulation(builder, reportFloatToFBS(planet.Population))
fbs.LocalPlanetAddColonists(builder, reportFloatToFBS(planet.Colonists))
fbs.LocalPlanetAddProduction(builder, production)
fbs.LocalPlanetAddFreeIndustry(builder, reportFloatToFBS(planet.FreeIndustry))
return fbs.LocalPlanetEnd(builder)
}
func encodeReportShipProduction(builder *flatbuffers.Builder, production *model.ShipProduction) flatbuffers.UOffsetT {
class := builder.CreateString(production.Class)
fbs.ShipProductionStart(builder)
fbs.ShipProductionAddPlanet(builder, uint64(production.Planet))
fbs.ShipProductionAddClass(builder, class)
fbs.ShipProductionAddCost(builder, reportFloatToFBS(production.Cost))
fbs.ShipProductionAddProdUsed(builder, reportFloatToFBS(production.ProdUsed))
fbs.ShipProductionAddPercent(builder, reportFloatToFBS(production.Percent))
fbs.ShipProductionAddFree(builder, reportFloatToFBS(production.Free))
return fbs.ShipProductionEnd(builder)
}
func encodeReportRoute(builder *flatbuffers.Builder, route *model.Route) flatbuffers.UOffsetT {
routeEntries := encodeReportRouteEntryVector(builder, route.Route)
fbs.RouteStart(builder)
fbs.RouteAddPlanet(builder, uint64(route.Planet))
if routeEntries != 0 {
fbs.RouteAddRoute(builder, routeEntries)
}
return fbs.RouteEnd(builder)
}
func encodeReportOtherPlanet(builder *flatbuffers.Builder, planet *model.OtherPlanet) flatbuffers.UOffsetT {
owner := builder.CreateString(planet.Owner)
name := builder.CreateString(planet.Name)
production := builder.CreateString(planet.Production)
fbs.OtherPlanetStart(builder)
fbs.OtherPlanetAddOwner(builder, owner)
fbs.OtherPlanetAddX(builder, reportFloatToFBS(planet.X))
fbs.OtherPlanetAddY(builder, reportFloatToFBS(planet.Y))
fbs.OtherPlanetAddNumber(builder, uint64(planet.Number))
fbs.OtherPlanetAddSize(builder, reportFloatToFBS(planet.Size))
fbs.OtherPlanetAddName(builder, name)
fbs.OtherPlanetAddResources(builder, reportFloatToFBS(planet.Resources))
fbs.OtherPlanetAddCapital(builder, reportFloatToFBS(planet.Capital))
fbs.OtherPlanetAddMaterial(builder, reportFloatToFBS(planet.Material))
fbs.OtherPlanetAddIndustry(builder, reportFloatToFBS(planet.Industry))
fbs.OtherPlanetAddPopulation(builder, reportFloatToFBS(planet.Population))
fbs.OtherPlanetAddColonists(builder, reportFloatToFBS(planet.Colonists))
fbs.OtherPlanetAddProduction(builder, production)
fbs.OtherPlanetAddFreeIndustry(builder, reportFloatToFBS(planet.FreeIndustry))
return fbs.OtherPlanetEnd(builder)
}
func encodeReportUninhabitedPlanet(builder *flatbuffers.Builder, planet *model.UninhabitedPlanet) flatbuffers.UOffsetT {
name := builder.CreateString(planet.Name)
fbs.UninhabitedPlanetStart(builder)
fbs.UninhabitedPlanetAddX(builder, reportFloatToFBS(planet.X))
fbs.UninhabitedPlanetAddY(builder, reportFloatToFBS(planet.Y))
fbs.UninhabitedPlanetAddNumber(builder, uint64(planet.Number))
fbs.UninhabitedPlanetAddSize(builder, reportFloatToFBS(planet.Size))
fbs.UninhabitedPlanetAddName(builder, name)
fbs.UninhabitedPlanetAddResources(builder, reportFloatToFBS(planet.Resources))
fbs.UninhabitedPlanetAddCapital(builder, reportFloatToFBS(planet.Capital))
fbs.UninhabitedPlanetAddMaterial(builder, reportFloatToFBS(planet.Material))
return fbs.UninhabitedPlanetEnd(builder)
}
func encodeReportUnidentifiedPlanet(builder *flatbuffers.Builder, planet *model.UnidentifiedPlanet) flatbuffers.UOffsetT {
fbs.UnidentifiedPlanetStart(builder)
fbs.UnidentifiedPlanetAddX(builder, reportFloatToFBS(planet.X))
fbs.UnidentifiedPlanetAddY(builder, reportFloatToFBS(planet.Y))
fbs.UnidentifiedPlanetAddNumber(builder, uint64(planet.Number))
return fbs.UnidentifiedPlanetEnd(builder)
}
func encodeReportLocalFleet(builder *flatbuffers.Builder, fleet *model.LocalFleet) flatbuffers.UOffsetT {
name := builder.CreateString(fleet.Name)
state := builder.CreateString(fleet.State)
fbs.LocalFleetStart(builder)
fbs.LocalFleetAddName(builder, name)
fbs.LocalFleetAddGroups(builder, uint64(fleet.Groups))
fbs.LocalFleetAddDestination(builder, uint64(fleet.Destination))
if fleet.Origin != nil {
fbs.LocalFleetAddOrigin(builder, uint64(*fleet.Origin))
}
if fleet.Range != nil {
fbs.LocalFleetAddRange(builder, reportFloatToFBS(*fleet.Range))
}
fbs.LocalFleetAddSpeed(builder, reportFloatToFBS(fleet.Speed))
fbs.LocalFleetAddState(builder, state)
return fbs.LocalFleetEnd(builder)
}
func encodeReportLocalGroup(builder *flatbuffers.Builder, group *model.LocalGroup) flatbuffers.UOffsetT {
class := builder.CreateString(group.Class)
cargo := builder.CreateString(group.Cargo)
state := builder.CreateString(group.State)
tech := encodeReportTechEntryVector(builder, group.Tech)
var fleet flatbuffers.UOffsetT
if group.Fleet != nil {
fleet = builder.CreateString(*group.Fleet)
}
idHi, idLo := reportUUIDToHiLo(group.ID)
fbs.LocalGroupStart(builder)
fbs.LocalGroupAddNumber(builder, uint64(group.Number))
fbs.LocalGroupAddClass(builder, class)
if tech != 0 {
fbs.LocalGroupAddTech(builder, tech)
}
fbs.LocalGroupAddCargo(builder, cargo)
fbs.LocalGroupAddLoad(builder, reportFloatToFBS(group.Load))
fbs.LocalGroupAddDestination(builder, uint64(group.Destination))
if group.Origin != nil {
fbs.LocalGroupAddOrigin(builder, uint64(*group.Origin))
}
if group.Range != nil {
fbs.LocalGroupAddRange(builder, reportFloatToFBS(*group.Range))
}
fbs.LocalGroupAddSpeed(builder, reportFloatToFBS(group.Speed))
fbs.LocalGroupAddMass(builder, reportFloatToFBS(group.Mass))
fbs.LocalGroupAddId(builder, fbs.CreateUUID(builder, idHi, idLo))
fbs.LocalGroupAddState(builder, state)
if group.Fleet != nil {
fbs.LocalGroupAddFleet(builder, fleet)
}
return fbs.LocalGroupEnd(builder)
}
func encodeReportOtherGroup(builder *flatbuffers.Builder, group *model.OtherGroup) flatbuffers.UOffsetT {
class := builder.CreateString(group.Class)
cargo := builder.CreateString(group.Cargo)
tech := encodeReportTechEntryVector(builder, group.Tech)
fbs.OtherGroupStart(builder)
fbs.OtherGroupAddNumber(builder, uint64(group.Number))
fbs.OtherGroupAddClass(builder, class)
if tech != 0 {
fbs.OtherGroupAddTech(builder, tech)
}
fbs.OtherGroupAddCargo(builder, cargo)
fbs.OtherGroupAddLoad(builder, reportFloatToFBS(group.Load))
fbs.OtherGroupAddDestination(builder, uint64(group.Destination))
if group.Origin != nil {
fbs.OtherGroupAddOrigin(builder, uint64(*group.Origin))
}
if group.Range != nil {
fbs.OtherGroupAddRange(builder, reportFloatToFBS(*group.Range))
}
fbs.OtherGroupAddSpeed(builder, reportFloatToFBS(group.Speed))
fbs.OtherGroupAddMass(builder, reportFloatToFBS(group.Mass))
return fbs.OtherGroupEnd(builder)
}
func encodeReportUnidentifiedGroup(builder *flatbuffers.Builder, group *model.UnidentifiedGroup) flatbuffers.UOffsetT {
fbs.UnidentifiedGroupStart(builder)
fbs.UnidentifiedGroupAddX(builder, reportFloatToFBS(group.X))
fbs.UnidentifiedGroupAddY(builder, reportFloatToFBS(group.Y))
return fbs.UnidentifiedGroupEnd(builder)
}
func decodeReportPlayerVector(flatReport *fbs.Report, result *model.Report) error {
length := flatReport.PlayerLength()
if length == 0 {
return nil
}
result.Player = make([]model.Player, length)
item := new(fbs.Player)
for i := 0; i < length; i++ {
if !flatReport.Player(item, i) {
return fmt.Errorf("decode report player %d: player is missing", i)
}
result.Player[i] = model.Player{
Name: string(item.Name()),
Drive: reportFloatFromFBS(item.Drive()),
Weapons: reportFloatFromFBS(item.Weapons()),
Shields: reportFloatFromFBS(item.Shields()),
Cargo: reportFloatFromFBS(item.Cargo()),
Population: reportFloatFromFBS(item.Population()),
Industry: reportFloatFromFBS(item.Industry()),
Planets: item.Planets(),
Relation: string(item.Relation()),
Votes: reportFloatFromFBS(item.Votes()),
Extinct: item.Extinct(),
}
}
return nil
}
func decodeReportLocalScienceVector(flatReport *fbs.Report, result *model.Report) error {
length := flatReport.LocalScienceLength()
if length == 0 {
return nil
}
result.LocalScience = make([]model.Science, length)
item := new(fbs.Science)
for i := 0; i < length; i++ {
if !flatReport.LocalScience(item, i) {
return fmt.Errorf("decode report local science %d: science is missing", i)
}
result.LocalScience[i] = model.Science{
Name: string(item.Name()),
Drive: reportFloatFromFBS(item.Drive()),
Weapons: reportFloatFromFBS(item.Weapons()),
Shields: reportFloatFromFBS(item.Shields()),
Cargo: reportFloatFromFBS(item.Cargo()),
}
}
return nil
}
func decodeReportOtherScienceVector(flatReport *fbs.Report, result *model.Report) error {
length := flatReport.OtherScienceLength()
if length == 0 {
return nil
}
result.OtherScience = make([]model.OtherScience, length)
item := new(fbs.OtherScience)
for i := 0; i < length; i++ {
if !flatReport.OtherScience(item, i) {
return fmt.Errorf("decode report other science %d: science is missing", i)
}
result.OtherScience[i] = model.OtherScience{
Race: string(item.Race()),
Science: model.Science{
Name: string(item.Name()),
Drive: reportFloatFromFBS(item.Drive()),
Weapons: reportFloatFromFBS(item.Weapons()),
Shields: reportFloatFromFBS(item.Shields()),
Cargo: reportFloatFromFBS(item.Cargo()),
},
}
}
return nil
}
func decodeReportLocalShipClassVector(flatReport *fbs.Report, result *model.Report) error {
length := flatReport.LocalShipClassLength()
if length == 0 {
return nil
}
result.LocalShipClass = make([]model.ShipClass, length)
item := new(fbs.ShipClass)
for i := 0; i < length; i++ {
if !flatReport.LocalShipClass(item, i) {
return fmt.Errorf("decode report local ship class %d: ship class is missing", i)
}
armament, err := uint64ToUint(item.Armament(), "armament")
if err != nil {
return fmt.Errorf("decode report local ship class %d: %w", i, err)
}
result.LocalShipClass[i] = model.ShipClass{
Name: string(item.Name()),
Drive: reportFloatFromFBS(item.Drive()),
Armament: armament,
Weapons: reportFloatFromFBS(item.Weapons()),
Shields: reportFloatFromFBS(item.Shields()),
Cargo: reportFloatFromFBS(item.Cargo()),
Mass: reportFloatFromFBS(item.Mass()),
}
}
return nil
}
func decodeReportOtherShipClassVector(flatReport *fbs.Report, result *model.Report) error {
length := flatReport.OtherShipClassLength()
if length == 0 {
return nil
}
result.OtherShipClass = make([]model.OthersShipClass, length)
item := new(fbs.OthersShipClass)
for i := 0; i < length; i++ {
if !flatReport.OtherShipClass(item, i) {
return fmt.Errorf("decode report other ship class %d: ship class is missing", i)
}
armament, err := uint64ToUint(item.Armament(), "armament")
if err != nil {
return fmt.Errorf("decode report other ship class %d: %w", i, err)
}
result.OtherShipClass[i] = model.OthersShipClass{
Race: string(item.Race()),
ShipClass: model.ShipClass{
Name: string(item.Name()),
Drive: reportFloatFromFBS(item.Drive()),
Armament: armament,
Weapons: reportFloatFromFBS(item.Weapons()),
Shields: reportFloatFromFBS(item.Shields()),
Cargo: reportFloatFromFBS(item.Cargo()),
Mass: reportFloatFromFBS(item.Mass()),
},
}
}
return nil
}
func decodeReportBattleVector(flatReport *fbs.Report, result *model.Report) error {
length := flatReport.BattleLength()
if length == 0 {
return nil
}
result.Battle = make([]uuid.UUID, length)
item := new(fbs.UUID)
for i := 0; i < length; i++ {
if !flatReport.Battle(item, i) {
return fmt.Errorf("decode report battle %d: battle id is missing", i)
}
result.Battle[i] = reportUUIDFromHiLo(item.Hi(), item.Lo())
}
return nil
}
func decodeReportBombingVector(flatReport *fbs.Report, result *model.Report) error {
length := flatReport.BombingLength()
if length == 0 {
return nil
}
result.Bombing = make([]*model.Bombing, length)
item := new(fbs.Bombing)
for i := 0; i < length; i++ {
if !flatReport.Bombing(item, i) {
return fmt.Errorf("decode report bombing %d: bombing is missing", i)
}
number, err := uint64ToUint(item.Number(), "number")
if err != nil {
return fmt.Errorf("decode report bombing %d: %w", i, err)
}
result.Bombing[i] = &model.Bombing{
Number: number,
Planet: string(item.Planet()),
Owner: string(item.Owner()),
Attacker: string(item.Attacker()),
Production: string(item.Production()),
Industry: reportFloatFromFBS(item.Industry()),
Population: reportFloatFromFBS(item.Population()),
Colonists: reportFloatFromFBS(item.Colonists()),
Capital: reportFloatFromFBS(item.Capital()),
Material: reportFloatFromFBS(item.Material()),
AttackPower: reportFloatFromFBS(item.AttackPower()),
Wiped: item.Wiped(),
}
}
return nil
}
func decodeReportIncomingGroupVector(flatReport *fbs.Report, result *model.Report) error {
length := flatReport.IncomingGroupLength()
if length == 0 {
return nil
}
result.IncomingGroup = make([]model.IncomingGroup, length)
item := new(fbs.IncomingGroup)
for i := 0; i < length; i++ {
if !flatReport.IncomingGroup(item, i) {
return fmt.Errorf("decode report incoming group %d: group is missing", i)
}
origin, err := uint64ToUint(item.Origin(), "origin")
if err != nil {
return fmt.Errorf("decode report incoming group %d: %w", i, err)
}
destination, err := uint64ToUint(item.Destination(), "destination")
if err != nil {
return fmt.Errorf("decode report incoming group %d: %w", i, err)
}
result.IncomingGroup[i] = model.IncomingGroup{
Origin: origin,
Destination: destination,
Distance: reportFloatFromFBS(item.Distance()),
Speed: reportFloatFromFBS(item.Speed()),
Mass: reportFloatFromFBS(item.Mass()),
}
}
return nil
}
func decodeReportLocalPlanetVector(flatReport *fbs.Report, result *model.Report) error {
length := flatReport.LocalPlanetLength()
if length == 0 {
return nil
}
result.LocalPlanet = make([]model.LocalPlanet, length)
item := new(fbs.LocalPlanet)
for i := 0; i < length; i++ {
if !flatReport.LocalPlanet(item, i) {
return fmt.Errorf("decode report local planet %d: planet is missing", i)
}
number, err := uint64ToUint(item.Number(), "number")
if err != nil {
return fmt.Errorf("decode report local planet %d: %w", i, err)
}
result.LocalPlanet[i] = model.LocalPlanet{
UninhabitedPlanet: model.UninhabitedPlanet{
UnidentifiedPlanet: model.UnidentifiedPlanet{
X: reportFloatFromFBS(item.X()),
Y: reportFloatFromFBS(item.Y()),
Number: number,
},
Size: reportFloatFromFBS(item.Size()),
Name: string(item.Name()),
Resources: reportFloatFromFBS(item.Resources()),
Capital: reportFloatFromFBS(item.Capital()),
Material: reportFloatFromFBS(item.Material()),
},
Industry: reportFloatFromFBS(item.Industry()),
Population: reportFloatFromFBS(item.Population()),
Colonists: reportFloatFromFBS(item.Colonists()),
Production: string(item.Production()),
FreeIndustry: reportFloatFromFBS(item.FreeIndustry()),
}
}
return nil
}
func decodeReportShipProductionVector(flatReport *fbs.Report, result *model.Report) error {
length := flatReport.ShipProductionLength()
if length == 0 {
return nil
}
result.ShipProduction = make([]model.ShipProduction, length)
item := new(fbs.ShipProduction)
for i := 0; i < length; i++ {
if !flatReport.ShipProduction(item, i) {
return fmt.Errorf("decode report ship production %d: production is missing", i)
}
planet, err := uint64ToUint(item.Planet(), "planet")
if err != nil {
return fmt.Errorf("decode report ship production %d: %w", i, err)
}
result.ShipProduction[i] = model.ShipProduction{
Planet: planet,
Class: string(item.Class()),
Cost: reportFloatFromFBS(item.Cost()),
ProdUsed: reportFloatFromFBS(item.ProdUsed()),
Percent: reportFloatFromFBS(item.Percent()),
Free: reportFloatFromFBS(item.Free()),
}
}
return nil
}
func decodeReportRouteVector(flatReport *fbs.Report, result *model.Report) error {
length := flatReport.RouteLength()
if length == 0 {
return nil
}
result.Route = make([]model.Route, length)
item := new(fbs.Route)
for i := 0; i < length; i++ {
if !flatReport.Route(item, i) {
return fmt.Errorf("decode report route %d: route is missing", i)
}
planet, err := uint64ToUint(item.Planet(), "planet")
if err != nil {
return fmt.Errorf("decode report route %d: %w", i, err)
}
routeMap, err := decodeReportRouteMap(item, i)
if err != nil {
return err
}
result.Route[i] = model.Route{
Planet: planet,
Route: routeMap,
}
}
return nil
}
func decodeReportOtherPlanetVector(flatReport *fbs.Report, result *model.Report) error {
length := flatReport.OtherPlanetLength()
if length == 0 {
return nil
}
result.OtherPlanet = make([]model.OtherPlanet, length)
item := new(fbs.OtherPlanet)
for i := 0; i < length; i++ {
if !flatReport.OtherPlanet(item, i) {
return fmt.Errorf("decode report other planet %d: planet is missing", i)
}
number, err := uint64ToUint(item.Number(), "number")
if err != nil {
return fmt.Errorf("decode report other planet %d: %w", i, err)
}
result.OtherPlanet[i] = model.OtherPlanet{
Owner: string(item.Owner()),
LocalPlanet: model.LocalPlanet{
UninhabitedPlanet: model.UninhabitedPlanet{
UnidentifiedPlanet: model.UnidentifiedPlanet{
X: reportFloatFromFBS(item.X()),
Y: reportFloatFromFBS(item.Y()),
Number: number,
},
Size: reportFloatFromFBS(item.Size()),
Name: string(item.Name()),
Resources: reportFloatFromFBS(item.Resources()),
Capital: reportFloatFromFBS(item.Capital()),
Material: reportFloatFromFBS(item.Material()),
},
Industry: reportFloatFromFBS(item.Industry()),
Population: reportFloatFromFBS(item.Population()),
Colonists: reportFloatFromFBS(item.Colonists()),
Production: string(item.Production()),
FreeIndustry: reportFloatFromFBS(item.FreeIndustry()),
},
}
}
return nil
}
func decodeReportUninhabitedPlanetVector(flatReport *fbs.Report, result *model.Report) error {
length := flatReport.UninhabitedPlanetLength()
if length == 0 {
return nil
}
result.UninhabitedPlanet = make([]model.UninhabitedPlanet, length)
item := new(fbs.UninhabitedPlanet)
for i := 0; i < length; i++ {
if !flatReport.UninhabitedPlanet(item, i) {
return fmt.Errorf("decode report uninhabited planet %d: planet is missing", i)
}
number, err := uint64ToUint(item.Number(), "number")
if err != nil {
return fmt.Errorf("decode report uninhabited planet %d: %w", i, err)
}
result.UninhabitedPlanet[i] = model.UninhabitedPlanet{
UnidentifiedPlanet: model.UnidentifiedPlanet{
X: reportFloatFromFBS(item.X()),
Y: reportFloatFromFBS(item.Y()),
Number: number,
},
Size: reportFloatFromFBS(item.Size()),
Name: string(item.Name()),
Resources: reportFloatFromFBS(item.Resources()),
Capital: reportFloatFromFBS(item.Capital()),
Material: reportFloatFromFBS(item.Material()),
}
}
return nil
}
func decodeReportUnidentifiedPlanetVector(flatReport *fbs.Report, result *model.Report) error {
length := flatReport.UnidentifiedPlanetLength()
if length == 0 {
return nil
}
result.UnidentifiedPlanet = make([]model.UnidentifiedPlanet, length)
item := new(fbs.UnidentifiedPlanet)
for i := 0; i < length; i++ {
if !flatReport.UnidentifiedPlanet(item, i) {
return fmt.Errorf("decode report unidentified planet %d: planet is missing", i)
}
number, err := uint64ToUint(item.Number(), "number")
if err != nil {
return fmt.Errorf("decode report unidentified planet %d: %w", i, err)
}
result.UnidentifiedPlanet[i] = model.UnidentifiedPlanet{
X: reportFloatFromFBS(item.X()),
Y: reportFloatFromFBS(item.Y()),
Number: number,
}
}
return nil
}
func decodeReportLocalFleetVector(flatReport *fbs.Report, result *model.Report) error {
length := flatReport.LocalFleetLength()
if length == 0 {
return nil
}
result.LocalFleet = make([]model.LocalFleet, length)
item := new(fbs.LocalFleet)
for i := 0; i < length; i++ {
if !flatReport.LocalFleet(item, i) {
return fmt.Errorf("decode report local fleet %d: fleet is missing", i)
}
groups, err := uint64ToUint(item.Groups(), "groups")
if err != nil {
return fmt.Errorf("decode report local fleet %d: %w", i, err)
}
destination, err := uint64ToUint(item.Destination(), "destination")
if err != nil {
return fmt.Errorf("decode report local fleet %d: %w", i, err)
}
decoded := model.LocalFleet{
Name: string(item.Name()),
Groups: groups,
Destination: destination,
Speed: reportFloatFromFBS(item.Speed()),
State: string(item.State()),
}
if origin := item.Origin(); origin != nil {
decodedOrigin, err := uint64ToUint(*origin, "origin")
if err != nil {
return fmt.Errorf("decode report local fleet %d: %w", i, err)
}
decoded.Origin = &decodedOrigin
}
if range_ := item.Range(); range_ != nil {
decodedRange := reportFloatFromFBS(*range_)
decoded.Range = &decodedRange
}
result.LocalFleet[i] = decoded
}
return nil
}
func decodeReportLocalGroupVector(flatReport *fbs.Report, result *model.Report) error {
length := flatReport.LocalGroupLength()
if length == 0 {
return nil
}
result.LocalGroup = make([]model.LocalGroup, length)
item := new(fbs.LocalGroup)
for i := 0; i < length; i++ {
if !flatReport.LocalGroup(item, i) {
return fmt.Errorf("decode report local group %d: group is missing", i)
}
number, err := uint64ToUint(item.Number(), "number")
if err != nil {
return fmt.Errorf("decode report local group %d: %w", i, err)
}
destination, err := uint64ToUint(item.Destination(), "destination")
if err != nil {
return fmt.Errorf("decode report local group %d: %w", i, err)
}
tech, err := decodeReportTechMapFromLocalGroup(item, i)
if err != nil {
return err
}
id := item.Id(nil)
if id == nil {
return fmt.Errorf("decode report local group %d: id is missing", i)
}
decoded := model.LocalGroup{
OtherGroup: model.OtherGroup{
Number: number,
Class: string(item.Class()),
Tech: tech,
Cargo: string(item.Cargo()),
Load: reportFloatFromFBS(item.Load()),
Destination: destination,
Speed: reportFloatFromFBS(item.Speed()),
Mass: reportFloatFromFBS(item.Mass()),
},
ID: reportUUIDFromHiLo(id.Hi(), id.Lo()),
State: string(item.State()),
}
if origin := item.Origin(); origin != nil {
decodedOrigin, err := uint64ToUint(*origin, "origin")
if err != nil {
return fmt.Errorf("decode report local group %d: %w", i, err)
}
decoded.Origin = &decodedOrigin
}
if range_ := item.Range(); range_ != nil {
decodedRange := reportFloatFromFBS(*range_)
decoded.Range = &decodedRange
}
if fleet := item.Fleet(); fleet != nil {
decodedFleet := string(fleet)
decoded.Fleet = &decodedFleet
}
result.LocalGroup[i] = decoded
}
return nil
}
func decodeReportOtherGroupVector(flatReport *fbs.Report, result *model.Report) error {
length := flatReport.OtherGroupLength()
if length == 0 {
return nil
}
result.OtherGroup = make([]model.OtherGroup, length)
item := new(fbs.OtherGroup)
for i := 0; i < length; i++ {
if !flatReport.OtherGroup(item, i) {
return fmt.Errorf("decode report other group %d: group is missing", i)
}
number, err := uint64ToUint(item.Number(), "number")
if err != nil {
return fmt.Errorf("decode report other group %d: %w", i, err)
}
destination, err := uint64ToUint(item.Destination(), "destination")
if err != nil {
return fmt.Errorf("decode report other group %d: %w", i, err)
}
tech, err := decodeReportTechMapFromOtherGroup(item, i)
if err != nil {
return err
}
decoded := model.OtherGroup{
Number: number,
Class: string(item.Class()),
Tech: tech,
Cargo: string(item.Cargo()),
Load: reportFloatFromFBS(item.Load()),
Destination: destination,
Speed: reportFloatFromFBS(item.Speed()),
Mass: reportFloatFromFBS(item.Mass()),
}
if origin := item.Origin(); origin != nil {
decodedOrigin, err := uint64ToUint(*origin, "origin")
if err != nil {
return fmt.Errorf("decode report other group %d: %w", i, err)
}
decoded.Origin = &decodedOrigin
}
if range_ := item.Range(); range_ != nil {
decodedRange := reportFloatFromFBS(*range_)
decoded.Range = &decodedRange
}
result.OtherGroup[i] = decoded
}
return nil
}
func decodeReportUnidentifiedGroupVector(flatReport *fbs.Report, result *model.Report) error {
length := flatReport.UnidentifiedGroupLength()
if length == 0 {
return nil
}
result.UnidentifiedGroup = make([]model.UnidentifiedGroup, length)
item := new(fbs.UnidentifiedGroup)
for i := 0; i < length; i++ {
if !flatReport.UnidentifiedGroup(item, i) {
return fmt.Errorf("decode report unidentified group %d: group is missing", i)
}
result.UnidentifiedGroup[i] = model.UnidentifiedGroup{
X: reportFloatFromFBS(item.X()),
Y: reportFloatFromFBS(item.Y()),
}
}
return nil
}
func decodeReportRouteMap(flatRoute *fbs.Route, routeIndex int) (map[uint]string, error) {
length := flatRoute.RouteLength()
if length == 0 {
return nil, nil
}
result := make(map[uint]string, length)
item := new(fbs.RouteEntry)
for i := 0; i < length; i++ {
if !flatRoute.Route(item, i) {
return nil, fmt.Errorf("decode report route %d entry %d: route entry is missing", routeIndex, i)
}
key, err := uint64ToUint(item.Key(), "route key")
if err != nil {
return nil, fmt.Errorf("decode report route %d entry %d: %w", routeIndex, i, err)
}
result[key] = string(item.Value())
}
return result, nil
}
func decodeReportTechMapFromOtherGroup(group *fbs.OtherGroup, groupIndex int) (map[string]model.Float, error) {
length := group.TechLength()
if length == 0 {
return nil, nil
}
result := make(map[string]model.Float, length)
item := new(fbs.TechEntry)
for i := 0; i < length; i++ {
if !group.Tech(item, i) {
return nil, fmt.Errorf("decode report other group %d tech entry %d: tech entry is missing", groupIndex, i)
}
result[string(item.Key())] = reportFloatFromFBS(item.Value())
}
return result, nil
}
func decodeReportTechMapFromLocalGroup(group *fbs.LocalGroup, groupIndex int) (map[string]model.Float, error) {
length := group.TechLength()
if length == 0 {
return nil, nil
}
result := make(map[string]model.Float, length)
item := new(fbs.TechEntry)
for i := 0; i < length; i++ {
if !group.Tech(item, i) {
return nil, fmt.Errorf("decode report local group %d tech entry %d: tech entry is missing", groupIndex, i)
}
result[string(item.Key())] = reportFloatFromFBS(item.Value())
}
return result, nil
}
func encodeReportOffsetVector(
builder *flatbuffers.Builder,
length int,
startVector func(*flatbuffers.Builder, int) flatbuffers.UOffsetT,
offsets []flatbuffers.UOffsetT,
) flatbuffers.UOffsetT {
if length == 0 {
return 0
}
startVector(builder, length)
for i := length - 1; i >= 0; i-- {
builder.PrependUOffsetT(offsets[i])
}
return builder.EndVector(length)
}
func encodeReportUUIDVector(builder *flatbuffers.Builder, ids []uuid.UUID) flatbuffers.UOffsetT {
if len(ids) == 0 {
return 0
}
fbs.ReportStartBattleVector(builder, len(ids))
for i := len(ids) - 1; i >= 0; i-- {
hi, lo := reportUUIDToHiLo(ids[i])
fbs.CreateUUID(builder, hi, lo)
}
return builder.EndVector(len(ids))
}
func encodeReportRouteEntryVector(builder *flatbuffers.Builder, route map[uint]string) flatbuffers.UOffsetT {
if len(route) == 0 {
return 0
}
keys := make([]uint, 0, len(route))
for key := range route {
keys = append(keys, key)
}
sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })
offsets := make([]flatbuffers.UOffsetT, len(keys))
for i, key := range keys {
value := builder.CreateString(route[key])
fbs.RouteEntryStart(builder)
fbs.RouteEntryAddKey(builder, uint64(key))
fbs.RouteEntryAddValue(builder, value)
offsets[i] = fbs.RouteEntryEnd(builder)
}
fbs.RouteStartRouteVector(builder, len(offsets))
for i := len(offsets) - 1; i >= 0; i-- {
builder.PrependUOffsetT(offsets[i])
}
return builder.EndVector(len(offsets))
}
func encodeReportTechEntryVector(builder *flatbuffers.Builder, tech map[string]model.Float) flatbuffers.UOffsetT {
if len(tech) == 0 {
return 0
}
keys := make([]string, 0, len(tech))
for key := range tech {
keys = append(keys, key)
}
sort.Strings(keys)
offsets := make([]flatbuffers.UOffsetT, len(keys))
for i, key := range keys {
encodedKey := builder.CreateString(key)
fbs.TechEntryStart(builder)
fbs.TechEntryAddKey(builder, encodedKey)
fbs.TechEntryAddValue(builder, reportFloatToFBS(tech[key]))
offsets[i] = fbs.TechEntryEnd(builder)
}
fbs.OtherGroupStartTechVector(builder, len(offsets))
for i := len(offsets) - 1; i >= 0; i-- {
builder.PrependUOffsetT(offsets[i])
}
return builder.EndVector(len(offsets))
}
func reportFloatToFBS(value model.Float) float32 {
return float32(value.F())
}
func reportFloatFromFBS(value float32) model.Float {
return model.Float(float64(value))
}
func reportUUIDToHiLo(value uuid.UUID) (uint64, uint64) {
return binary.BigEndian.Uint64(value[0:8]), binary.BigEndian.Uint64(value[8:16])
}
func reportUUIDFromHiLo(hi uint64, lo uint64) uuid.UUID {
var value uuid.UUID
binary.BigEndian.PutUint64(value[0:8], hi)
binary.BigEndian.PutUint64(value[8:16], lo)
return value
}
func uint64ToUint(value uint64, field string) (uint, error) {
maxUint := uint64(^uint(0))
if value > maxUint {
return 0, fmt.Errorf("%s value %d overflows uint", field, value)
}
return uint(value), nil
}