- Add DTOs instead of entities to response

- Remove hotkey from wiki data
- Add souls cost to units
This commit is contained in:
Anibus 2025-04-18 14:01:43 +03:00
parent 3666b92626
commit 97537b6ccf
31 changed files with 374 additions and 40 deletions

View File

@ -1,5 +1,6 @@
package com.dowstats.controllers
import com.dowstats.data.dto.controllers.BuildingFullDto
import com.dowstats.data.dto.controllers.RaceBuildings
import com.dowstats.data.dto.controllers.RaceUnits
import com.dowstats.data.entities.Building
@ -36,8 +37,8 @@ class BuildingsController @Autowired constructor(
@GetMapping("/{buildingId}")
fun getById(@PathVariable buildingId: Long): Building {
return buildingRepository.findById(buildingId).get()
fun getById(@PathVariable buildingId: Long): BuildingFullDto {
return buildingRepository.findById(buildingId).get().toDto()
}
@DeleteMapping

View File

@ -1,6 +1,7 @@
package com.dowstats.controllers
import com.dowstats.data.dto.controllers.RaceUnits
import com.dowstats.data.dto.controllers.UnitFullDto
import com.dowstats.data.entities.DowUnit
import com.dowstats.data.repositories.UnitRepository
import com.dowstats.service.datamaps.DowUnitMappingService
@ -32,8 +33,8 @@ class UnitsController @Autowired constructor(
@GetMapping("/{unitId}")
fun getById(@PathVariable unitId: Long): DowUnit {
return unitsRepo.findById(unitId).get()
fun getById(@PathVariable unitId: Long): UnitFullDto {
return unitsRepo.findById(unitId).get().toDto()
}
@DeleteMapping

View File

@ -0,0 +1,6 @@
package com.dowstats.data.dto.controllers
data class ArmorTypeDto(
val id: String,
val name: String?,
)

View File

@ -0,0 +1,15 @@
package com.dowstats.data.dto.controllers
data class BuildingAddonDto(
val id: Long?,
val name: String?,
val description: String?,
val filename: String?,
val addonCostRequisition: Double?,
val addonCostPower: Double?,
val addonCostPopulation: Double?,
val addonCostFaith: Double?,
val addonCostSouls: Double?,
val addonCostTime: Int?,
val icon: String?,
)

View File

@ -0,0 +1,26 @@
package com.dowstats.data.dto.controllers
data class BuildingFullDto(
var id: Long?,
var race: RaceDto?,
var armorType: ArmorTypeDto?,
var armorType2: ArmorTypeDto?,
var name: String?,
var description: String?,
var filename: String?,
var buildCostRequisition: Double?,
var buildCostPower: Double?,
var buildCostPopulation: Double?,
var buildCostFaith: Double?,
var buildCostSouls: Double?,
var buildCostTime: Int?,
var health: Int?,
var healthRegeneration: Double?,
var sightRadius: Int?,
var detectRadius: Int?,
var repairMax: Int?,
var icon: String?,
var modId: Long?,
var addons: MutableSet<BuildingAddonDto>?,
val weapons: Set<WeaponSlotDto>?,
)

View File

@ -1,13 +1,11 @@
package com.dowstats.data.dto.controllers
import com.dowstats.data.entities.Race
data class RaceBuildings(
val race: Race,
val buildings: List<BuildingDto>,
val race: RaceDto,
val buildings: List<BuildingShortDto>,
)
data class BuildingDto(
data class BuildingShortDto(
val name: String,
val icon: String,
val id: Long,

View File

@ -0,0 +1,6 @@
package com.dowstats.data.dto.controllers
data class RaceDto(
val id: String,
val name: String?,
)

View File

@ -0,0 +1,26 @@
package com.dowstats.data.dto.controllers
data class SergeantDto(
val id: Long?,
val armorType: ArmorTypeDto?,
val armorType2: ArmorTypeDto?,
val name: String?,
val description: String?,
val filename: String,
val buildCostRequisition: Double?,
val buildCostPower: Double?,
val buildCostPopulation: Double?,
val buildCostFaith: Double?,
val buildCostSouls: Double?,
val buildCostTime: Int?,
val health: Int?,
val healthRegeneration: Double?,
val moraleDeathPenalty: Int?,
val mass: Int?,
val upTime: Double?,
val sightRadius: Int?,
val detectRadius: Int?,
val icon: String?,
val weapons: List<WeaponSlotDto>?,
)

View File

@ -0,0 +1,45 @@
package com.dowstats.data.dto.controllers
data class UnitFullDto(
val id: Long,
val race: RaceDto?,
val armorType: ArmorTypeDto?,
val armorType2: ArmorTypeDto?,
val name: String?,
val description: String?,
val filename: String,
val buildCostRequisition: Double?,
val buildCostPower: Double?,
val buildCostPopulation: Double?,
val buildCostFaith: Double?,
val buildCostSouls: Double?,
val buildCostTime: Int?,
val capInfantry: Int?,
val capSupport: Int?,
val squadStartSize: Int?,
val squadMaxSize: Int?,
val squadLimit: Int?,
val health: Int?,
val healthRegeneration: Double?,
val moraleDeathPenalty: Int?,
val moraleMax: Int?,
val moraleBroken: Int?,
val moraleRegeneration: Int?,
val mass: Int?,
val upTime: Double?,
val moveSpeed: Int?,
val sightRadius: Int?,
val detectRadius: Int?,
val reinforceCostRequisition: Int?,
val reinforceCostPower: Int?,
val reinforceCostPopulation: Int?,
val reinforceCostFaith: Int?,
val reinforceCostSouls: Int?,
val reinforceTime: Int?,
val maxSergeants: Int?,
val icon: String?,
val modId: Long,
val sergeants: Set<SergeantDto>?,
val weapons: Set<WeaponSlotDto>?,
)

View File

@ -1,18 +1,17 @@
package com.dowstats.data.dto.controllers
import com.dowstats.data.entities.Race
data class RaceUnits(
val race: Race,
val infantry: List<UnitDto>,
val tech: List<UnitDto>,
val support: List<UnitDto>,
val race: RaceDto,
val infantry: List<UnitShortDto>,
val tech: List<UnitShortDto>,
val support: List<UnitShortDto>,
)
data class UnitDto(
data class UnitShortDto(
val name: String,
val icon: String,
val id: Long,
val armourTypeName: String,
val canDetect: Boolean,
)
)

View File

@ -0,0 +1,8 @@
package com.dowstats.data.dto.controllers
import java.math.BigDecimal
data class WeaponArmorPiercingDto(
val armorType: ArmorTypeDto?,
val piercingValue: BigDecimal,
)

View File

@ -0,0 +1,31 @@
package com.dowstats.data.dto.controllers
data class WeaponDto(
val id: Long?,
val filename: String,
val name: String?,
val description: String?,
val costRequisition: Int?,
val costPower: Int?,
val costTimeSeconds: Int?,
val accuracy: Double?,
val reloadTime: Double?,
val minRange: Double?,
val maxRange: Double?,
val setupTime: Double?,
val accuracyReductionMoving: Double?,
val minDamage: Double?,
val maxDamage: Double?,
val minDamageValue: Double?,
val moraleDamage: Double?,
val damageRadius: Double?,
val throwForceMin: Double?,
val throwForceMax: Double?,
val isMeleeWeapon: Boolean,
val canAttackAir: Boolean,
val canAttackGround: Boolean,
val icon: String?,
val haveEquipButton: Boolean,
val modId: Long?,
val weaponArmorPiercing: List<WeaponArmorPiercingDto>
)

View File

@ -0,0 +1,7 @@
package com.dowstats.data.dto.controllers
data class WeaponSlotDto(
val hardpoint: Int,
val hardpointOrder: Int,
val weapon: WeaponDto,
)

View File

@ -1,5 +1,6 @@
package com.dowstats.data.entities
import com.dowstats.data.dto.controllers.ArmorTypeDto
import jakarta.persistence.*
@ -11,4 +12,9 @@ class ArmorType {
@GeneratedValue(strategy = GenerationType.AUTO)
var id: String? = null
var name: String? = null
fun toDto() = ArmorTypeDto(
id!!,
name
)
}

View File

@ -1,5 +1,6 @@
package com.dowstats.data.entities
import com.dowstats.data.dto.controllers.BuildingFullDto
import jakarta.persistence.*
@ -46,5 +47,31 @@ class Building {
@OneToMany(mappedBy = "building", cascade = [CascadeType.ALL])
var weapons: MutableSet<BuildingWeapon>? = null
fun toDto(): BuildingFullDto =
BuildingFullDto(
id!!,
race?.toDto(),
armorType?.toDto(),
armorType2?.toDto(),
name,
description,
filename!!,
buildCostRequisition,
buildCostPower,
buildCostPopulation,
buildCostFaith,
buildCostSouls,
buildCostTime,
health,
healthRegeneration,
sightRadius,
detectRadius,
repairMax,
icon,
modId!!,
mutableSetOf(),
weapons?.map { it.toWeaponSlotDto() }?.toSet(),
)
}

View File

@ -1,5 +1,6 @@
package com.dowstats.data.entities
import com.dowstats.data.dto.controllers.WeaponSlotDto
import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.*
import java.io.Serializable
@ -39,4 +40,10 @@ class BuildingWeapon {
@JoinColumn(name = "weapon_id")
var weapon: Weapon? = null
fun toWeaponSlotDto() = WeaponSlotDto(
buildingWeaponKey!!.hardpoint,
buildingWeaponKey!!.hardpointOrder,
weapon?.toDto()!!
)
}

View File

@ -1,5 +1,6 @@
package com.dowstats.data.entities
import com.dowstats.data.dto.controllers.UnitFullDto
import jakarta.persistence.*
@ -52,6 +53,7 @@ class DowUnit {
var reinforceCostPower: Int? = null
var reinforceCostPopulation: Int? = null
var reinforceCostFaith: Int? = null
var reinforceCostSouls: Int? = null
var reinforceTime: Int? = null
var maxSergeants: Int? = null
var icon: String? = null
@ -64,4 +66,47 @@ class DowUnit {
var weapons: MutableSet<UnitWeapon>? = null
fun toDto(): UnitFullDto =
UnitFullDto(
id!!,
race?.toDto(),
armorType?.toDto(),
armorType2?.toDto(),
name,
description,
filename!!,
buildCostRequisition,
buildCostPower,
buildCostPopulation,
buildCostFaith,
buildCostSouls,
buildCostTime,
capInfantry,
capSupport,
squadStartSize,
squadMaxSize,
squadLimit,
health,
healthRegeneration,
moraleDeathPenalty,
moraleMax,
moraleBroken,
moraleRegeneration,
mass,
upTime,
moveSpeed,
sightRadius,
detectRadius,
reinforceCostRequisition,
reinforceCostPower,
reinforceCostPopulation,
reinforceCostFaith,
reinforceCostSouls,
reinforceTime,
maxSergeants,
icon,
modId!!,
sergeants?.map { it.toDto() }?.toSet(),
weapons?.map { it.toWeaponSlotDto() }?.toSet()
)
}

View File

@ -1,5 +1,6 @@
package com.dowstats.data.entities
import com.dowstats.data.dto.controllers.RaceDto
import jakarta.persistence.*
@ -11,4 +12,10 @@ class Race {
var id: String? = null
var name: String? = null
fun toDto(): RaceDto =
RaceDto(
id!!,
name,
)
}

View File

@ -1,5 +1,6 @@
package com.dowstats.data.entities
import com.dowstats.data.dto.controllers.SergeantDto
import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.*
@ -46,5 +47,28 @@ class Sergeant {
@OneToMany(mappedBy = "sergeant", cascade = [CascadeType.ALL])
var weapons: MutableSet<SergeantWeapon>? = null
fun toDto(): SergeantDto =
SergeantDto(
id!!,
armorType?.toDto(),
armorType2?.toDto(),
name,
description,
filename!!,
buildCostRequisition,
buildCostPower,
buildCostPopulation,
buildCostFaith,
buildCostSouls,
buildCostTime,
health,
healthRegeneration,
moraleDeathPenalty,
mass,
upTime,
sightRadius,
detectRadius,
icon,
weapons?.map { it.toWeaponSlotDto() }
)
}

View File

@ -1,5 +1,6 @@
package com.dowstats.data.entities
import com.dowstats.data.dto.controllers.WeaponSlotDto
import com.fasterxml.jackson.annotation.JsonIgnore
import java.io.Serializable
import jakarta.persistence.*
@ -38,4 +39,10 @@ class SergeantWeapon {
@MapsId("weaponId")
@JoinColumn(name = "weapon_id")
var weapon: Weapon? = null
fun toWeaponSlotDto() = WeaponSlotDto(
sergeantWeaponKey!!.hardpoint,
sergeantWeaponKey!!.hardpointOrder,
weapon?.toDto()!!
)
}

View File

@ -1,5 +1,6 @@
package com.dowstats.data.entities
import com.dowstats.data.dto.controllers.WeaponSlotDto
import com.fasterxml.jackson.annotation.JsonIgnore
import java.io.Serializable
import jakarta.persistence.*
@ -40,4 +41,10 @@ class UnitWeapon {
@JoinColumn(name = "weapon_id")
var weapon: Weapon? = null
fun toWeaponSlotDto() = WeaponSlotDto(
unitWeaponKey!!.hardpoint,
unitWeaponKey!!.hardpointOrder,
weapon?.toDto()!!
)
}

View File

@ -1,5 +1,6 @@
package com.dowstats.data.entities
import com.dowstats.data.dto.controllers.WeaponDto
import jakarta.persistence.*
@ -34,7 +35,6 @@ class Weapon {
var canAttackGround: Boolean = true
var icon: String? = null
var haveEquipButton: Boolean = true
var hotkeyName: String? = null
var modId: Long? = null
@Transient
@ -45,4 +45,34 @@ class Weapon {
@OneToMany(mappedBy="weapon", fetch = FetchType.EAGER, cascade = [(CascadeType.ALL)])
var weaponPiercings: List<WeaponArmorPiercing> = listOf()
fun toDto() = WeaponDto(
id!!,
filename!!,
name,
description,
costRequisition,
costPower,
costTimeSeconds,
accuracy,
reloadTime,
minRange,
maxRange,
setupTime,
accuracyReductionMoving,
minDamage,
maxDamage,
minDamageValue,
moraleDamage,
damageRadius,
throwForceMin,
throwForceMax,
isMeleeWeapon,
canAttackAir,
canAttackGround,
icon,
haveEquipButton,
modId,
weaponPiercings.map { it.toDto() }
)
}

View File

@ -1,5 +1,6 @@
package com.dowstats.data.entities
import com.dowstats.data.dto.controllers.WeaponArmorPiercingDto
import com.fasterxml.jackson.annotation.JsonIgnore
import java.math.BigDecimal
import jakarta.persistence.*
@ -23,4 +24,9 @@ class WeaponArmorPiercing {
var armorType: ArmorType? = null
var piercingValue: BigDecimal? = null
fun toDto() = WeaponArmorPiercingDto(
armorType?.toDto(),
piercingValue?:BigDecimal.ZERO,
)
}

View File

@ -14,6 +14,7 @@ interface BuildingRepository : CrudRepository<Building, Long>{
left join fetch ArmorType a2 on b.armorType2.id = a2.id
where b.modId = :modId
and (:race is null or b.race = :race)
order by b.race.id desc
""")
fun findByModIdAndRace(modId: Long, race: Race?): List<Building>
}

View File

@ -14,6 +14,7 @@ interface UnitRepository : CrudRepository<DowUnit, Long> {
left join fetch ArmorType a2 on d.armorType2.id = a2.id
where d.modId = :modId
and (:race is null or d.race = :race)
order by d.race.id desc
""")
fun findByModIdAndRace(modId: Long, race: Race?): List<DowUnit>

View File

@ -1,15 +1,10 @@
package com.dowstats.service.datamaps
import com.dowstats.data.dto.controllers.BuildingDto
import com.dowstats.data.dto.controllers.BuildingShortDto
import com.dowstats.data.dto.controllers.RaceBuildings
import com.dowstats.data.dto.controllers.RaceUnits
import com.dowstats.data.dto.controllers.UnitDto
import com.dowstats.data.entities.Building
import com.dowstats.data.entities.DowUnit
import com.dowstats.data.entities.Race
import com.dowstats.data.repositories.BuildingRepository
import com.dowstats.data.repositories.RaceRepository
import com.dowstats.data.repositories.UnitRepository
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
@ -21,23 +16,22 @@ class DowBuildingMappingService @Autowired constructor(
fun findBuildingsByMod(modId: Long): List<RaceBuildings> {
return getAllBuildings(modId).groupBy { it.race }.mapNotNull {raceUnits ->
RaceBuildings(raceUnits.key ?: throw Exception("Race is null"), raceUnits.value.toBuildingDto())
RaceBuildings(raceUnits.key?.toDto() ?: throw Exception("Race is null"), raceUnits.value.toBuildingDto())
}
}
fun findBuildingsByModAndRace(modId: Long, race: String): RaceBuildings {
val buildings = getAllBuildings(modId, race)
val raceEntity = race.let{ raceRepository.findById(race) ?: throw Exception("Race $race not found") }
return RaceBuildings(raceEntity, buildings.toBuildingDto())
return RaceBuildings(raceEntity.toDto(), buildings.toBuildingDto())
}
private fun List<Building>.toBuildingDto(): List<BuildingDto> =
private fun List<Building>.toBuildingDto(): List<BuildingShortDto> =
this.mapNotNull {
val name = it.name ?: it.filename
val icon = it.icon
if (name == null || icon == null) null else BuildingDto(name, icon, it.id!!,
if (name == null || icon == null) null else BuildingShortDto(name, icon, it.id!!,
it.armorType?.name!!,
(it.detectRadius ?: 0) > 0)
}
@ -61,5 +55,6 @@ class DowBuildingMappingService @Autowired constructor(
&& it.filename?.contains("tau_squad_slave_murdered") != true
&& it.filename?.contains("space_marine_single_player_only_drop_pod_building_2.rgd") != true
&& it.filename?.contains("space_marine_single_player_only_drop_pod_building.rgd") != true
&& it.filename?.contains("space_marine_drop_pod_building.rgd") != true
}
}

View File

@ -1,7 +1,7 @@
package com.dowstats.service.datamaps
import com.dowstats.data.dto.controllers.RaceUnits
import com.dowstats.data.dto.controllers.UnitDto
import com.dowstats.data.dto.controllers.UnitShortDto
import com.dowstats.data.entities.DowUnit
import com.dowstats.data.entities.Race
import com.dowstats.data.repositories.RaceRepository
@ -43,15 +43,15 @@ class DowUnitMappingService @Autowired constructor(
}
.toUnitDto()
return RaceUnits(race, infantry, tech, support)
return RaceUnits(race.toDto(), infantry, tech, support)
}
private fun List<DowUnit>.toUnitDto(): List<UnitDto> =
private fun List<DowUnit>.toUnitDto(): List<UnitShortDto> =
this.mapNotNull {
val name = it.name ?: it.filename
val icon = it.icon
if (name == null || icon == null) null else UnitDto(name, icon, it.id!!,
if (name == null || icon == null) null else UnitShortDto(name, icon, it.id!!,
it.armorType?.name!!,
(it.detectRadius ?: 0) > 0)
}

View File

@ -119,6 +119,7 @@ class UnitRgdExtractService @Autowired constructor(
unit.reinforceCostPower = getReinforcePower(reinforceCostData)
unit.reinforceCostPopulation = getReinforcePopulation(reinforceCostData)
unit.reinforceCostFaith = getReinforceFaith(reinforceCostData)
unit.reinforceCostSouls = getReinforceSouls(reinforceCostData)
unit.reinforceTime = getReinforceTime(reinforceData)
val sergeantsData = getSergeantsData(squadData)
@ -319,6 +320,9 @@ class UnitRgdExtractService @Autowired constructor(
private fun getReinforceFaith(reinforceData: List<RgdData>?): Int? = reinforceData
?.getIntByName("faith")
private fun getReinforceSouls(reinforceData: List<RgdData>?): Int? = reinforceData
?.getIntByName("souls")
private fun getReinforceTime(reinforceData: List<RgdData>?): Int? = reinforceData
?.getIntByName("time_seconds")

View File

@ -63,7 +63,6 @@ class WeaponRgdExtractService @Autowired constructor(
weapon.icon = weaponUiData.iconPath
weapon.description = weaponUiData.description
weapon.haveEquipButton = weaponUiData.haveEquipButton
weapon.hotkeyName = weaponData.getStringByName("ui_hotkey_name")
val cost = getCost(weaponData)
weapon.costRequisition = cost.requisition ?: 0

View File

@ -190,6 +190,11 @@
"name": "reinforce_cost_faith",
"type": "int"
}
},{
"column": {
"name": "reinforce_cost_souls",
"type": "number"
}
},{
"column": {
"name": "reinforce_time",

View File

@ -203,12 +203,6 @@
"type": "varchar(128)"
}
},
{
"column": {
"name": "hotkey_name",
"type": "varchar(64)"
}
},
{
"column": {
"name": "mod_id",