package error import ( "fmt" ) const ( ErrStorageFailure int = 1000 + iota ErrGameNotInitialized ErrGameStateInvalid ErrReportNotFound ) const ( ErrDummy int = -1 ErrDeleteShipTypeExistingGroup = 5000 ErrDeleteShipTypePlanetProduction = 5001 ErrDeleteSciencePlanetProduction = 5002 ErrMergeShipTypeNotEqual = 5003 ErrJoinFleetGroupNumberNotEnough = 5004 ErrBeakGroupNumberNotEnough = 5005 ErrEntityInUse = 5006 ErrShipsBusy = 5007 ErrShipsNotOnSamePlanet = 5008 ErrGiveawayGroupShipsTypeNotEqual = 5009 ErrUpgradeGroupNumberNotEnough = 5010 ErrUpgradeInsufficientResources = 5011 ErrSendShipHasNoDrives = 5012 ErrSendUnreachableDestination = 5013 ErrRaceExinct = 5014 ) const ( ErrInputUnknownRace int = 3000 + iota ErrInputSameRace ErrInputEntityTypeNameInvalid ErrInputEntityTypeNameDuplicate ErrInputEntityTypeNameEquality ErrInputEntityNotExists ErrInputEntityNotOwned ErrInputPlanetNumber ErrInputDriveValue ErrInputWeaponsValue ErrInputShieldsValue ErrInputCargoValue ErrInputShipTypeArmamentValue ErrInputShipTypeWeaponsAndArmamentValue ErrInputShipTypeZeroValues ErrInputScienceSumValues ErrInputProductionInvalid ErrInputCargoTypeInvalid ErrInputCargoQuantityWithoutGroupBreak ErrInputCargoLoadNotEnough ErrInputCargoLoadNotEqual ErrInputNoCargoBay ErrInputCargoLoadNoSpaceLeft ErrInputCargoUnloadEmpty ErrInputCargoUnoadNotEnough ErrInputBreakGroupIllegalNumber ErrInputTechUnknown ErrInputTechInvalidMixing ErrInputUpgradeShipTechNotUsed ErrInputUpgradeParameterNotAllowed ErrInputUpgradeShipsAlreadyUpToDate ErrInputUpgradeTechLevelInsufficient ) func GenericErrorText(code int) string { switch code { case ErrDummy: return "Dummy" case ErrStorageFailure: return "Storage failure" case ErrGameNotInitialized: return "Game not yet initialized" case ErrGameStateInvalid: return "Invalid game state" case ErrInputUnknownRace: return "Race name is unknown to this game" case ErrInputSameRace: return "Race name must be different from your own" case ErrInputEntityTypeNameInvalid: return "Name has invalid length or symbols" case ErrInputEntityTypeNameDuplicate: return "Name already exists" case ErrInputEntityTypeNameEquality: return "Names should differ" case ErrInputEntityNotExists: return "Entity does not exists" case ErrInputEntityNotOwned: return "Entity is not owned" case ErrEntityInUse: return "Entity currently in use" case ErrInputPlanetNumber: return "Invalid Planet number" case ErrInputDriveValue: return "Invalid Drive value" case ErrInputWeaponsValue: return "Invalid Weapons value" case ErrInputShieldsValue: return "Invalid Shields value" case ErrInputCargoValue: return "Invalid Cargo value" case ErrInputShipTypeArmamentValue: return "Invalid Armament value" case ErrInputShipTypeWeaponsAndArmamentValue: return "Invalid Armament or Weapons value" case ErrInputShipTypeZeroValues: return "Ship type values cannot be all zeros" case ErrDeleteShipTypeExistingGroup: return "Ship type exists in a Group" case ErrDeleteShipTypePlanetProduction: return "Ship type in production on the Planet" case ErrDeleteSciencePlanetProduction: return "Science in production on the Planet" case ErrInputScienceSumValues: return "Science proportions sum should be equal 1" case ErrInputProductionInvalid: return "Invalid Production type" case ErrInputCargoTypeInvalid: return "Invalid cargo type" case ErrInputCargoQuantityWithoutGroupBreak: return "Cargo quantity should be specified only for a new group number of ships" case ErrInputCargoLoadNotEnough: return "Not enough cargo to load" case ErrInputCargoLoadNotEqual: return "Ship(s) already loaded with another cargo" case ErrInputNoCargoBay: return "Ship type is not designed to carry cargo" case ErrInputCargoLoadNoSpaceLeft: return "No space left on the ships to load cargo" case ErrInputCargoUnloadEmpty: return "Ships are not carrying any cargo" case ErrInputCargoUnoadNotEnough: return "Not enough cargo on the ships(s)" case ErrInputBreakGroupIllegalNumber: return "Illegal ships number to make new group" case ErrMergeShipTypeNotEqual: return "Source and target ship types are not the same" case ErrJoinFleetGroupNumberNotEnough: return "Not enough ships in the group to join a fleet" case ErrBeakGroupNumberNotEnough: return "Not enough ships in the group to make a separate group" case ErrShipsBusy: return "Ship(s) are'n free to use" case ErrShipsNotOnSamePlanet: return "Ships not on the same planet" case ErrGiveawayGroupShipsTypeNotEqual: return "Ship type already defined with different specifications" case ErrInputTechUnknown: return "Technology name unknown" case ErrInputTechInvalidMixing: return "Technologies list must containt only specific values" case ErrInputUpgradeShipTechNotUsed: return "Technology is not used with ship class" case ErrInputUpgradeParameterNotAllowed: return "Parameter not allowed for upgrade" case ErrInputUpgradeShipsAlreadyUpToDate: return "Ships already up to date, nothing to upgrade" case ErrUpgradeGroupNumberNotEnough: return "Not enough ships in the group to make an upgrade" case ErrUpgradeInsufficientResources: return "Insufficient planet production capacity" case ErrInputUpgradeTechLevelInsufficient: return "Insifficient Tech level for requested upgrade" case ErrSendShipHasNoDrives: return "One or more ships are not equipped with hyperdrive and cannot be moved" case ErrSendUnreachableDestination: return "Destination planet is too far for current Drive level" case ErrRaceExinct: return "Race is extinct" default: return fmt.Sprintf("Undescribed error with code %d", code) } } type GenericError struct { Code int subject string err error } func (ge GenericError) Error() string { msg := GenericErrorText(ge.Code) if ge.subject != "" { msg += ": " + ge.subject } if ge.err != nil { msg = fmt.Errorf("%s: %w", msg, ge.err).Error() } return msg } func newGenericError(code int, arg ...any) error { e := &GenericError{Code: code} if len(arg) > 0 { i := 0 switch arg[i].(type) { case error: e.err = arg[i].(error) i += 1 } if len(arg) >= i+2 { e.subject = fmt.Sprintf(asString(arg[i]), arg[i+1:]...) } else if len(arg) == i+1 { e.subject = asString(arg[i]) } } return *e } func asString(v any) string { switch s := v.(type) { case string: return s default: return fmt.Sprint(v) } }