Optimization update

- move weapons and researches to separate controllers (optimization at frontend)
- add building affects data
This commit is contained in:
Anibus 2025-12-07 00:51:58 +03:00
parent 9b12eb3f51
commit c637580255
42 changed files with 813 additions and 119 deletions

View File

@ -0,0 +1,29 @@
package com.dowstats.controllers
import com.dowstats.data.dto.controllers.WeaponDto
import com.dowstats.data.dto.controllers.building.BuildingFullDto
import com.dowstats.data.dto.controllers.building.RaceBuildings
import com.dowstats.data.dto.controllers.research.ResearchDto
import com.dowstats.data.repositories.BuildingRepository
import com.dowstats.service.datamaps.DowBuildingMappingService
import com.dowstats.service.datamaps.ResearchService
import com.dowstats.service.datamaps.WeaponService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("api/v1/research")
class ResearchController @Autowired constructor(
val researchService: ResearchService,
) {
@GetMapping("/{modId}/{researchId}")
fun getById(@PathVariable researchId: Long, @PathVariable modId: Long): ResearchDto {
return researchService.getResearchDto(researchId, modId)
}
}

View File

@ -0,0 +1,35 @@
package com.dowstats.controllers
import com.dowstats.data.dto.controllers.WeaponDto
import com.dowstats.data.dto.controllers.building.BuildingFullDto
import com.dowstats.data.dto.controllers.building.RaceBuildings
import com.dowstats.data.repositories.BuildingRepository
import com.dowstats.service.datamaps.DowBuildingMappingService
import com.dowstats.service.datamaps.WeaponService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("api/v1/weapon")
class WeaponController @Autowired constructor(
val weaponService: WeaponService,
val buildingRepository: BuildingRepository,
) {
@GetMapping("/{modId}/{weaponId}")
fun getById(@PathVariable weaponId: Long, @PathVariable modId: Long): WeaponDto {
return weaponService.getWeaponDto(weaponId, modId)
}
@DeleteMapping
fun removeAll() {
buildingRepository.deleteAll()
}
}

View File

@ -1,8 +1,6 @@
package com.dowstats.data.dto package com.dowstats.data.dto
import com.dowstats.data.entities.Building import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.DowUnit
import com.dowstats.data.entities.Sergeant
import com.dowstats.data.entities.Weapon import com.dowstats.data.entities.Weapon
data class BuildingDataToSave( data class BuildingDataToSave(

View File

@ -1,6 +1,6 @@
package com.dowstats.data.dto.controllers package com.dowstats.data.dto.controllers
import com.dowstats.data.entities.Building import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.DowUnit import com.dowstats.data.entities.DowUnit
import com.dowstats.data.entities.Sergeant import com.dowstats.data.entities.Sergeant
import com.dowstats.data.entities.Weapon import com.dowstats.data.entities.Weapon

View File

@ -0,0 +1,12 @@
package com.dowstats.data.dto.controllers
import com.dowstats.data.dto.controllers.building.BuildingAddonShortDto
import com.dowstats.data.dto.controllers.research.ResearchShortDto
data class WeaponShortDto(
val id: Long?,
val filename: String,
val name: String?,
val icon: String?,
val isMeleeWeapon: Boolean?,
)

View File

@ -3,5 +3,5 @@ package com.dowstats.data.dto.controllers
data class WeaponSlotDto( data class WeaponSlotDto(
val hardpoint: Int, val hardpoint: Int,
val hardpointOrder: Int, val hardpointOrder: Int,
val weapon: WeaponDto, val weapon: WeaponShortDto,
) )

View File

@ -1,7 +1,6 @@
package com.dowstats.data.dto.controllers.building package com.dowstats.data.dto.controllers.building
import com.dowstats.data.dto.controllers.* import com.dowstats.data.dto.controllers.*
import com.dowstats.data.dto.controllers.research.ResearchDto
import com.dowstats.data.dto.controllers.research.ResearchShortDto import com.dowstats.data.dto.controllers.research.ResearchShortDto
data class BuildingFullDto( data class BuildingFullDto(
@ -30,7 +29,9 @@ data class BuildingFullDto(
var icon: String?, var icon: String?,
var modId: Long?, var modId: Long?,
var addons: List<BuildingAddonDto>?, var addons: List<BuildingAddonDto>?,
var researches: List<ResearchDto>?, var researches: List<ResearchShortDto>?,
var modifiers: List<ModifierDto>,
var affectedData: AffectedDataDto,
val units: List<UnitShortDto>, val units: List<UnitShortDto>,
val weapons: Set<WeaponSlotDto>, val weapons: Set<WeaponSlotDto>,
val requirements: RequirementDto?, val requirements: RequirementDto?,

View File

@ -4,5 +4,6 @@ data class ResearchShortDto(
val id: Long?, val id: Long?,
val name: String?, val name: String?,
val icon: String?, val icon: String?,
val uiIndexHint: Int?,
val buildingId: Long?, val buildingId: Long?,
) )

View File

@ -2,6 +2,7 @@ package com.dowstats.data.entities
import com.dowstats.data.dto.controllers.* import com.dowstats.data.dto.controllers.*
import com.dowstats.data.entities.addon.BuildingAddon import com.dowstats.data.entities.addon.BuildingAddon
import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.research.Research import com.dowstats.data.entities.research.Research
import jakarta.persistence.* import jakarta.persistence.*
@ -92,6 +93,12 @@ class DowUnit {
inverseJoinColumns = [JoinColumn(name = "addon_id")]) inverseJoinColumns = [JoinColumn(name = "addon_id")])
var affectedAddons: MutableSet<BuildingAddon> = mutableSetOf() var affectedAddons: MutableSet<BuildingAddon> = mutableSetOf()
@ManyToMany
@JoinTable(name = "building_affected_units",
joinColumns = [JoinColumn(name = "unit_id")],
inverseJoinColumns = [JoinColumn(name = "building_id")])
var affectedBuildings: MutableSet<Building> = mutableSetOf()
@OneToMany(mappedBy = "unit", cascade = [CascadeType.ALL]) @OneToMany(mappedBy = "unit", cascade = [CascadeType.ALL])
var unitRequirements: MutableSet<UnitRequirements> = mutableSetOf() var unitRequirements: MutableSet<UnitRequirements> = mutableSetOf()

View File

@ -0,0 +1,32 @@
package com.dowstats.data.entities
import com.dowstats.data.dto.controllers.EntityCompressDtoObject.compressDto
import com.dowstats.data.dto.controllers.SergeantUnitShortDto
import jakarta.persistence.GeneratedValue
import jakarta.persistence.GenerationType
import jakarta.persistence.Id
import jakarta.persistence.MappedSuperclass
@MappedSuperclass
open class ModifiersBase {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null
var reference: String? = null
var target: String? = null
var usageType: String? = null
var value: Double? = null
companion object ModifiersBaseCompanion {
fun <T : ModifiersBase> List<T>.filterUseless(): List<T> =
this.filterNot {
it.usageType == "type_modifierusagetype\\tp_mod_usage_addition.lua" && it.value == 0.0 ||
it.usageType == "type_modifierusagetype\\tp_mod_usage_multiplication.lua" && it.value == 1.0
}
}
}

View File

@ -5,6 +5,7 @@ import com.dowstats.data.dto.controllers.SergeantDto
import com.dowstats.data.dto.controllers.WeaponSlotDto import com.dowstats.data.dto.controllers.WeaponSlotDto
import com.dowstats.data.entities.Weapon.HardpointPosition import com.dowstats.data.entities.Weapon.HardpointPosition
import com.dowstats.data.entities.addon.BuildingAddon import com.dowstats.data.entities.addon.BuildingAddon
import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.research.Research import com.dowstats.data.entities.research.Research
import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.* import jakarta.persistence.*
@ -74,6 +75,12 @@ class Sergeant {
inverseJoinColumns = [JoinColumn(name = "addon_id")]) inverseJoinColumns = [JoinColumn(name = "addon_id")])
var affectedAddons: MutableSet<BuildingAddon> = mutableSetOf() var affectedAddons: MutableSet<BuildingAddon> = mutableSetOf()
@ManyToMany
@JoinTable(name = "building_affected_sergeants",
joinColumns = [JoinColumn(name = "sergeant_id")],
inverseJoinColumns = [JoinColumn(name = "building_id")])
var affectedBuildings: MutableSet<Building> = mutableSetOf()
@OneToMany(mappedBy = "sergeant", cascade = [CascadeType.ALL]) @OneToMany(mappedBy = "sergeant", cascade = [CascadeType.ALL])
var sergeantRequirements: MutableSet<SergeantRequirements> = mutableSetOf() var sergeantRequirements: MutableSet<SergeantRequirements> = mutableSetOf()

View File

@ -41,9 +41,9 @@ class SergeantWeapon {
@JoinColumn(name = "weapon_id") @JoinColumn(name = "weapon_id")
var weapon: Weapon? = null var weapon: Weapon? = null
fun toWeaponSlotDto(requirement: RequirementDto?) = WeaponSlotDto( fun toWeaponSlotDto() = WeaponSlotDto(
sergeantWeaponKey!!.hardpoint, sergeantWeaponKey!!.hardpoint,
sergeantWeaponKey!!.hardpointOrder, sergeantWeaponKey!!.hardpointOrder,
weapon?.toDto(requirement)!! weapon?.toShortDto()!!
) )
} }

View File

@ -42,10 +42,10 @@ class UnitWeapon {
@JoinColumn(name = "weapon_id") @JoinColumn(name = "weapon_id")
var weapon: Weapon? = null var weapon: Weapon? = null
fun toWeaponSlotDto(requirement: RequirementDto?) = WeaponSlotDto( fun toWeaponSlotDto() = WeaponSlotDto(
unitWeaponKey!!.hardpoint, unitWeaponKey!!.hardpoint,
unitWeaponKey!!.hardpointOrder, unitWeaponKey!!.hardpointOrder,
weapon?.toDto(requirement)!! weapon?.toShortDto()!!
) )
} }

View File

@ -2,7 +2,10 @@ package com.dowstats.data.entities
import com.dowstats.data.dto.controllers.RequirementDto import com.dowstats.data.dto.controllers.RequirementDto
import com.dowstats.data.dto.controllers.WeaponDto import com.dowstats.data.dto.controllers.WeaponDto
import com.dowstats.data.dto.controllers.WeaponShortDto
import com.dowstats.data.entities.addon.BuildingAddon import com.dowstats.data.entities.addon.BuildingAddon
import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.building.BuildingWeapon
import com.dowstats.data.entities.research.Research import com.dowstats.data.entities.research.Research
import jakarta.persistence.* import jakarta.persistence.*
@ -52,6 +55,12 @@ class Weapon {
inverseJoinColumns = [JoinColumn(name = "addon_id")]) inverseJoinColumns = [JoinColumn(name = "addon_id")])
var affectedAddons: MutableSet<BuildingAddon> = mutableSetOf() var affectedAddons: MutableSet<BuildingAddon> = mutableSetOf()
@ManyToMany
@JoinTable(name = "building_affected_weapons",
joinColumns = [JoinColumn(name = "weapon_id")],
inverseJoinColumns = [JoinColumn(name = "building_id")])
var affectedBuildings: MutableSet<Building> = mutableSetOf()
@OneToMany(mappedBy = "weapon", cascade = [CascadeType.ALL]) @OneToMany(mappedBy = "weapon", cascade = [CascadeType.ALL])
var unitsUse: MutableSet<UnitWeapon>? = null var unitsUse: MutableSet<UnitWeapon>? = null
@ -103,4 +112,12 @@ class Weapon {
affectedAddons.map { it.toShortDto() }.toSet(), affectedAddons.map { it.toShortDto() }.toSet(),
requirementDto, requirementDto,
) )
fun toShortDto() = WeaponShortDto(
id!!,
filename!!,
name,
icon,
isMeleeWeapon,
)
} }

View File

@ -1,28 +1,20 @@
package com.dowstats.data.entities.addon package com.dowstats.data.entities.addon
import com.dowstats.data.dto.controllers.ModifierDto import com.dowstats.data.dto.controllers.ModifierDto
import com.dowstats.data.entities.ModifiersBase
import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.* import jakarta.persistence.*
@Entity @Entity
@Table(name = "addon_modifiers") @Table(name = "addon_modifiers")
class AddonModifiers { class AddonModifiers : ModifiersBase() {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null
@ManyToOne @ManyToOne
@JoinColumn(name = "addon_id", nullable = false) @JoinColumn(name = "addon_id", nullable = false)
@JsonIgnore @JsonIgnore
var addon: BuildingAddon? = null var addon: BuildingAddon? = null
var reference: String? = null
var target: String? = null
var usageType: String? = null
var value: Double? = null
fun toDto(): ModifierDto { fun toDto(): ModifierDto {
return ModifierDto( return ModifierDto(
id = id!!, id = id!!,

View File

@ -3,12 +3,11 @@ package com.dowstats.data.entities.addon
import com.dowstats.data.dto.controllers.AffectedDataDto import com.dowstats.data.dto.controllers.AffectedDataDto
import com.dowstats.data.dto.controllers.EntityCompressDtoObject.compressDto import com.dowstats.data.dto.controllers.EntityCompressDtoObject.compressDto
import com.dowstats.data.dto.controllers.RequirementDto import com.dowstats.data.dto.controllers.RequirementDto
import com.dowstats.data.dto.controllers.SergeantUnitShortDto
import com.dowstats.data.dto.controllers.SergeantUnitShortDtoObject.toShortDtoSet import com.dowstats.data.dto.controllers.SergeantUnitShortDtoObject.toShortDtoSet
import com.dowstats.data.dto.controllers.WeaponUnitShortDtoObject.toShortDtoSet import com.dowstats.data.dto.controllers.WeaponUnitShortDtoObject.toShortDtoSet
import com.dowstats.data.dto.controllers.building.BuildingAddonDto import com.dowstats.data.dto.controllers.building.BuildingAddonDto
import com.dowstats.data.dto.controllers.building.BuildingAddonShortDto import com.dowstats.data.dto.controllers.building.BuildingAddonShortDto
import com.dowstats.data.entities.Building import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.DowUnit import com.dowstats.data.entities.DowUnit
import com.dowstats.data.entities.Sergeant import com.dowstats.data.entities.Sergeant
import com.dowstats.data.entities.Weapon import com.dowstats.data.entities.Weapon

View File

@ -1,15 +1,23 @@
package com.dowstats.data.entities package com.dowstats.data.entities.building
import com.dowstats.data.dto.controllers.AffectedDataDto
import com.dowstats.data.dto.controllers.EntityCompressDtoObject.compressDto
import com.dowstats.data.dto.controllers.RequirementDto import com.dowstats.data.dto.controllers.RequirementDto
import com.dowstats.data.dto.controllers.SergeantUnitShortDtoObject.toShortDtoSet
import com.dowstats.data.dto.controllers.WeaponSlotDto import com.dowstats.data.dto.controllers.WeaponSlotDto
import com.dowstats.data.dto.controllers.WeaponUnitShortDtoObject.toShortDtoSet
import com.dowstats.data.dto.controllers.building.BuildingAddonDto import com.dowstats.data.dto.controllers.building.BuildingAddonDto
import com.dowstats.data.dto.controllers.building.BuildingFullDto import com.dowstats.data.dto.controllers.building.BuildingFullDto
import com.dowstats.data.dto.controllers.research.ResearchDto import com.dowstats.data.dto.controllers.research.ResearchShortDto
import com.dowstats.data.entities.ArmorType
import com.dowstats.data.entities.DowUnit
import com.dowstats.data.entities.DowUnitObject.toUnitDto import com.dowstats.data.entities.DowUnitObject.toUnitDto
import com.dowstats.data.entities.Race
import com.dowstats.data.entities.Sergeant
import com.dowstats.data.entities.Weapon
import com.dowstats.data.entities.Weapon.HardpointPosition import com.dowstats.data.entities.Weapon.HardpointPosition
import com.dowstats.data.entities.addon.BuildingAddon import com.dowstats.data.entities.addon.BuildingAddon
import com.dowstats.data.entities.research.Research import com.dowstats.data.entities.research.Research
import com.dowstats.data.entities.research.ResearchRequirements
import jakarta.persistence.* import jakarta.persistence.*
@ -64,6 +72,9 @@ class Building {
@OneToMany(mappedBy = "building", cascade = [CascadeType.ALL]) @OneToMany(mappedBy = "building", cascade = [CascadeType.ALL])
var weapons: MutableSet<BuildingWeapon>? = null var weapons: MutableSet<BuildingWeapon>? = null
@OneToMany(mappedBy = "building", cascade = [CascadeType.ALL])
var modifiers: MutableSet<BuildingModifiers> = mutableSetOf()
@ManyToMany @ManyToMany
@JoinTable(name = "buildings_units", @JoinTable(name = "buildings_units",
joinColumns = [JoinColumn(name = "building_id")], joinColumns = [JoinColumn(name = "building_id")],
@ -76,6 +87,31 @@ class Building {
inverseJoinColumns = [JoinColumn(name = "research_id")]) inverseJoinColumns = [JoinColumn(name = "research_id")])
var researches: MutableSet<Research>? = null var researches: MutableSet<Research>? = null
@ManyToMany
@JoinTable(name = "building_affected_units",
joinColumns = [JoinColumn(name = "building_id")],
inverseJoinColumns = [JoinColumn(name = "unit_id")])
var affectedOnUnits: MutableSet<DowUnit> = mutableSetOf()
@ManyToMany
@JoinTable(name = "building_affected_sergeants",
joinColumns = [JoinColumn(name = "building_id")],
inverseJoinColumns = [JoinColumn(name = "sergeant_id")])
var affectedOnSergeants: MutableSet<Sergeant> = mutableSetOf()
@ManyToMany
@JoinTable(name = "building_affected_buildings",
joinColumns = [JoinColumn(name = "building_id")],
inverseJoinColumns = [JoinColumn(name = "building_id_affected")])
var affectedOnBuildings: MutableSet<Building> = mutableSetOf()
@ManyToMany
@JoinTable(name = "building_affected_weapons",
joinColumns = [JoinColumn(name = "building_id")],
inverseJoinColumns = [JoinColumn(name = "weapon_id")])
var affectedOnWeapons: MutableSet<Weapon> = mutableSetOf()
@ManyToMany @ManyToMany
@JoinTable(name = "researches_affected_buildings", @JoinTable(name = "researches_affected_buildings",
joinColumns = [JoinColumn(name = "building_id")], joinColumns = [JoinColumn(name = "building_id")],
@ -88,13 +124,19 @@ class Building {
inverseJoinColumns = [JoinColumn(name = "addon_id")]) inverseJoinColumns = [JoinColumn(name = "addon_id")])
var affectedAddons: MutableSet<BuildingAddon> = mutableSetOf() var affectedAddons: MutableSet<BuildingAddon> = mutableSetOf()
@ManyToMany
@JoinTable(name = "building_affected_buildings",
joinColumns = [JoinColumn(name = "building_id_affected")],
inverseJoinColumns = [JoinColumn(name = "building_id")])
var affectedBuildings: MutableSet<Building> = mutableSetOf()
@OneToMany(mappedBy = "building", cascade = [CascadeType.ALL]) @OneToMany(mappedBy = "building", cascade = [CascadeType.ALL])
var buildingRequirements: MutableSet<BuildingRequirements> = mutableSetOf() var buildingRequirements: MutableSet<BuildingRequirements> = mutableSetOf()
@Transient @Transient
var weaponHardpoints: MutableSet<HardpointPosition> = mutableSetOf() var weaponHardpoints: MutableSet<HardpointPosition> = mutableSetOf()
fun toDto(buildingAddons: List<BuildingAddonDto>?, researches: List<ResearchDto>?, weapons: Set<WeaponSlotDto>, requirement: RequirementDto?): BuildingFullDto = fun toDto(buildingAddons: List<BuildingAddonDto>?, researches: List<ResearchShortDto>?, weapons: Set<WeaponSlotDto>, requirement: RequirementDto?): BuildingFullDto =
BuildingFullDto( BuildingFullDto(
id!!, id!!,
race?.toDto(), race?.toDto(),
@ -122,6 +164,13 @@ class Building {
modId!!, modId!!,
buildingAddons, buildingAddons,
researches, researches,
modifiers.map { it.toDto() },
AffectedDataDto(
affectedOnUnits.map { it.compressDto() }.toSet(),
affectedOnSergeants.toShortDtoSet(),
affectedOnBuildings.map { it.compressDto() }.toSet(),
affectedOnWeapons.toShortDtoSet(),
),
units?.toList()?.sortedBy { it.uiIndexHint }?.toUnitDto() ?: emptyList(), units?.toList()?.sortedBy { it.uiIndexHint }?.toUnitDto() ?: emptyList(),
weapons, weapons,
requirement, requirement,

View File

@ -0,0 +1,27 @@
package com.dowstats.data.entities.building
import com.dowstats.data.dto.controllers.ModifierDto
import com.dowstats.data.entities.ModifiersBase
import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.*
@Entity
@Table(name = "building_modifiers")
class BuildingModifiers : ModifiersBase() {
@ManyToOne
@JoinColumn(name = "building_id", nullable = false)
@JsonIgnore
var building: Building? = null
fun toDto(): ModifierDto {
return ModifierDto(
id = id!!,
reference = reference,
usageType = usageType,
value = value,
target = target,
)
}
}

View File

@ -1,5 +1,6 @@
package com.dowstats.data.entities package com.dowstats.data.entities.building
import com.dowstats.data.entities.RequirementBase
import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.Entity import jakarta.persistence.Entity
import jakarta.persistence.JoinColumn import jakarta.persistence.JoinColumn

View File

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

View File

@ -8,7 +8,7 @@ import com.dowstats.data.dto.controllers.SergeantUnitShortDtoObject.toShortDtoSe
import com.dowstats.data.dto.controllers.WeaponUnitShortDtoObject.toShortDtoSet import com.dowstats.data.dto.controllers.WeaponUnitShortDtoObject.toShortDtoSet
import com.dowstats.data.dto.controllers.research.ResearchDto import com.dowstats.data.dto.controllers.research.ResearchDto
import com.dowstats.data.dto.controllers.research.ResearchShortDto import com.dowstats.data.dto.controllers.research.ResearchShortDto
import com.dowstats.data.entities.Building import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.DowUnit import com.dowstats.data.entities.DowUnit
import com.dowstats.data.entities.Sergeant import com.dowstats.data.entities.Sergeant
import com.dowstats.data.entities.Weapon import com.dowstats.data.entities.Weapon
@ -75,6 +75,7 @@ class Research {
id = id!!, id = id!!,
name = name, name = name,
icon = icon, icon = icon,
uiIndexHint = uiIndexHint,
buildings?.firstOrNull()?.id buildings?.firstOrNull()?.id
) )

View File

@ -1,28 +1,20 @@
package com.dowstats.data.entities.research package com.dowstats.data.entities.research
import com.dowstats.data.dto.controllers.ModifierDto import com.dowstats.data.dto.controllers.ModifierDto
import com.dowstats.data.entities.ModifiersBase
import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.* import jakarta.persistence.*
@Entity @Entity
@Table(name = "research_modifiers") @Table(name = "research_modifiers")
class ResearchModifiers { class ResearchModifiers : ModifiersBase() {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null
@ManyToOne @ManyToOne
@JoinColumn(name = "research_id", nullable = false) @JoinColumn(name = "research_id", nullable = false)
@JsonIgnore @JsonIgnore
var research: Research? = null var research: Research? = null
var reference: String? = null
var target: String? = null
var usageType: String? = null
var value: Double? = null
fun toDto(): ModifierDto { fun toDto(): ModifierDto {
return ModifierDto( return ModifierDto(
id = id!!, id = id!!,

View File

@ -1,7 +1,6 @@
package com.dowstats.data.repositories package com.dowstats.data.repositories
import com.dowstats.data.entities.Building import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.DowUnit
import com.dowstats.data.entities.Race import com.dowstats.data.entities.Race
import org.springframework.data.jpa.repository.Query import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.CrudRepository import org.springframework.data.repository.CrudRepository

View File

@ -1,22 +1,22 @@
package com.dowstats.service.datamaps package com.dowstats.service.datamaps
import com.dowstats.data.dto.controllers.building.BuildingShortDto import com.dowstats.data.dto.controllers.building.BuildingShortDto
import com.dowstats.data.entities.Building import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.DowUnitObject.toUnitDto import com.dowstats.data.entities.DowUnitObject.toUnitDto
object CommonMapping { object CommonMapping {
fun List<Building>.toBuildingShortDto(): List<BuildingShortDto> = fun List<Building>.toBuildingShortDto(withoutUnits: Boolean = false): List<BuildingShortDto> =
this this
.sortedBy { it.uiIndexHint } .sortedWith(compareBy<Building> { it.uiIndexHint }.thenBy{ it.buildCostRequisition?.let { 0 - it } })
.mapNotNull {it.toBuildingShortDto() } .mapNotNull {it.toBuildingShortDto(withoutUnits) }
fun Building.toBuildingShortDto(): BuildingShortDto? { fun Building.toBuildingShortDto(withoutUnits: Boolean = false): BuildingShortDto? {
val name = this.name ?: this.filename?.replace(".rgd", "")?.replace("_", " ") val name = this.name ?: this.filename?.replace(".rgd", "")?.replace("_", " ")
val icon = this.icon val icon = this.icon
return if (name == null || icon == null) null else BuildingShortDto( return if (name == null || icon == null) null else BuildingShortDto(
name, icon, this.id!!, name, icon, this.id!!,
this.filename!!, this.filename!!,
this.units?.toList()?.sortedBy { it.uiIndexHint }?.toUnitDto() ?: emptyList(), if(!withoutUnits) { this.units?.toList()?.sortedBy { it.uiIndexHint }?.toUnitDto() ?: emptyList()} else emptyList(),
this.armorType?.name!!, this.armorType?.name!!,
(this.detectRadius ?: 0) > 0, (this.detectRadius ?: 0) > 0,
) )

View File

@ -3,7 +3,7 @@ package com.dowstats.service.datamaps
import com.dowstats.Metadata.Requirements import com.dowstats.Metadata.Requirements
import com.dowstats.data.dto.controllers.building.BuildingFullDto import com.dowstats.data.dto.controllers.building.BuildingFullDto
import com.dowstats.data.dto.controllers.building.RaceBuildings import com.dowstats.data.dto.controllers.building.RaceBuildings
import com.dowstats.data.entities.Building import com.dowstats.data.entities.building.Building
import com.dowstats.data.repositories.BuildingRepository import com.dowstats.data.repositories.BuildingRepository
import com.dowstats.data.repositories.RaceRepository import com.dowstats.data.repositories.RaceRepository
import com.dowstats.service.datamaps.CommonMapping.toBuildingShortDto import com.dowstats.service.datamaps.CommonMapping.toBuildingShortDto
@ -20,8 +20,8 @@ class DowBuildingMappingService @Autowired constructor(
fun findBuildingsByMod(modId: Long): List<RaceBuildings> { fun findBuildingsByMod(modId: Long): List<RaceBuildings> {
return getAllBuildings(modId).groupBy { it.race }.mapNotNull { raceBuildings -> return getAllBuildings(modId).groupBy { it.race }.mapNotNull { raceBuildings ->
RaceBuildings(raceBuildings.key?.toDto() ?: throw Exception("Race is null"), RaceBuildings(raceBuildings.key?.toDto() ?: throw Exception("Race is null"),
raceBuildings.value.filter { !it.advancedBuildOption }.toBuildingShortDto(), raceBuildings.value.filter { !it.advancedBuildOption }.toBuildingShortDto(withoutUnits = true),
raceBuildings.value.filter { it.advancedBuildOption }.toBuildingShortDto(),) raceBuildings.value.filter { it.advancedBuildOption }.toBuildingShortDto(withoutUnits = true),)
} }
} }
@ -50,10 +50,7 @@ class DowBuildingMappingService @Autowired constructor(
} }
val researches = building.researches?.map {research -> val researches = building.researches?.map {research ->
val requirements = requirementsMappingComponent research.toResearchShortDto()
.getRequirements(research.researchRequirements.toList() ?: emptyList(),
building.modId!!)
research.toResearchDto(requirements)
}?.sortedBy { it.uiIndexHint } }?.sortedBy { it.uiIndexHint }
val requirementDto = requirementsMappingComponent val requirementDto = requirementsMappingComponent
@ -61,10 +58,7 @@ class DowBuildingMappingService @Autowired constructor(
building.modId!!) building.modId!!)
val weapons = building.weapons?.map { buildingWeapon -> val weapons = building.weapons?.map { buildingWeapon ->
val requirements = requirementsMappingComponent buildingWeapon.toWeaponSlotDto()
.getRequirements(buildingWeapon.weapon?.weaponRequirements?.toList() ?: emptyList(),
building.modId!!)
buildingWeapon.toWeaponSlotDto(requirements)
}?.toSet() ?: emptySet() }?.toSet() ?: emptySet()
return building.toDto(buildingAddons, researches, weapons, requirementDto) return building.toDto(buildingAddons, researches, weapons, requirementDto)

View File

@ -34,11 +34,7 @@ class DowUnitMappingService @Autowired constructor(
) )
val weapons = unit.weapons?.map { unitWeapon -> val weapons = unit.weapons?.map { unitWeapon ->
val requirements = requirementsMappingComponent unitWeapon.toWeaponSlotDto()
.getRequirements(unitWeapon.weapon?.weaponRequirements?.toList() ?: emptyList(),
unit.modId!!,
)
unitWeapon.toWeaponSlotDto(requirements)
}?.toSet() ?: emptySet() }?.toSet() ?: emptySet()
return unitRepository.findById(unitId).get().toDto( return unitRepository.findById(unitId).get().toDto(
@ -61,11 +57,7 @@ class DowUnitMappingService @Autowired constructor(
) )
val weapons = sergeant.weapons?.map { sergeantWeapon -> val weapons = sergeant.weapons?.map { sergeantWeapon ->
val requirements = requirementsMappingComponent sergeantWeapon.toWeaponSlotDto()
.getRequirements(sergeantWeapon.weapon?.weaponRequirements?.toList() ?: emptyList(),
sergeant.modId!!,
)
sergeantWeapon.toWeaponSlotDto(requirements)
}?.toSet() ?: emptySet() }?.toSet() ?: emptySet()
return sergeant.toDto(weapons, requirementDto) return sergeant.toDto(weapons, requirementDto)

View File

@ -22,7 +22,7 @@ class RequirementsMappingComponent(
val requireCap = val requireCap =
requirements.find { it.reference == Requirements.REFERENCE_REQUIREMENT_POP }?.value?.toDouble() requirements.find { it.reference == Requirements.REFERENCE_REQUIREMENT_POP }?.value?.toDouble()
?.toInt() ?.toInt()?.let { if(it == 0) null else it }
val requiredOwnership = val requiredOwnership =
requirements.filter { it.reference == Requirements.REFERENCE_REQUIREMENT_OWNERSHIP } requirements.filter { it.reference == Requirements.REFERENCE_REQUIREMENT_OWNERSHIP }

View File

@ -0,0 +1,24 @@
package com.dowstats.service.datamaps
import com.dowstats.data.dto.controllers.research.ResearchDto
import com.dowstats.data.repositories.ResearchRepository
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
@Service
class ResearchService @Autowired constructor(
val researchRepository: ResearchRepository,
val requirementsMappingComponent: RequirementsMappingComponent,
) {
fun getResearchDto(id: Long, modId: Long): ResearchDto {
val research = researchRepository.findById(id).get()
val requirements = requirementsMappingComponent
.getRequirements(research.researchRequirements.toList() ,
modId)
return research.toResearchDto(requirements)
}
}

View File

@ -0,0 +1,33 @@
package com.dowstats.service.datamaps
import com.dowstats.data.dto.controllers.RaceUnits
import com.dowstats.data.dto.controllers.SergeantDto
import com.dowstats.data.dto.controllers.UnitFullDto
import com.dowstats.data.dto.controllers.WeaponDto
import com.dowstats.data.entities.DowUnit
import com.dowstats.data.entities.DowUnitObject.toUnitDto
import com.dowstats.data.entities.Race
import com.dowstats.data.entities.Sergeant
import com.dowstats.data.repositories.RaceRepository
import com.dowstats.data.repositories.UnitRepository
import com.dowstats.data.repositories.WeaponRepository
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
@Service
class WeaponService @Autowired constructor(
val weaponRepository: WeaponRepository,
val requirementsMappingComponent: RequirementsMappingComponent,
) {
fun getWeaponDto(id: Long, modId: Long): WeaponDto {
val weapon = weaponRepository.findById(id).get()
val requirements = requirementsMappingComponent
.getRequirements(weapon.weaponRequirements.toList(),
modId)
return weapon.toDto(requirements)
}
}

View File

@ -1,18 +1,13 @@
package com.dowstats.service.postparsing package com.dowstats.service.postparsing
import com.dowstats.configuration.StorageConfig
import com.dowstats.data.entities.* import com.dowstats.data.entities.*
import com.dowstats.data.entities.addon.BuildingAddon import com.dowstats.data.entities.addon.BuildingAddon
import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.research.Research import com.dowstats.data.entities.research.Research
import com.dowstats.data.repositories.* import com.dowstats.data.repositories.*
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
import java.awt.image.BufferedImage
import java.io.File
import java.nio.file.Path
import javax.imageio.ImageIO
import kotlin.io.path.exists
@Service @Service
@ -47,6 +42,11 @@ class PostParsingService @Autowired constructor(
bindAddonBuildings(buildings, addons) bindAddonBuildings(buildings, addons)
bindAddonWeapons(weapons, addons) bindAddonWeapons(weapons, addons)
bindBuildingUnits(units, buildings)
bindBuildingSergeants(sergeants, buildings)
bindBuildingToAffectedBuildings(buildings)
bindBuildingWeapons(weapons, buildings)
} catch (e: Exception) { } catch (e: Exception) {
log.warn("Error occurred during bind researches", e) log.warn("Error occurred during bind researches", e)
} }
@ -172,4 +172,64 @@ class PostParsingService @Autowired constructor(
weaponRepository.saveAll(weaponsWithBindings) weaponRepository.saveAll(weaponsWithBindings)
log.info("Successfully bind addons to weapons") log.info("Successfully bind addons to weapons")
} }
private fun bindBuildingUnits(units: List<DowUnit>, buildings: List<Building>) {
val unitsWithBindings: List<DowUnit> = buildings.flatMap { building ->
building.modifiers.mapNotNull { modifier ->
units.find {
it.filenameSquad?.replace(".rgd", "") == modifier.target ||
it.filenameUnit?.replace(".rgd", "") == modifier.target
}
?.let {
it.affectedBuildings.add(building)
it
}
}
}
unitRepository.saveAll(unitsWithBindings)
log.info("Successfully bind buildings to units")
}
private fun bindBuildingSergeants(sergeants: List<Sergeant>, buildings: List<Building>) {
val sergeantsWithBindings: List<Sergeant> = buildings.flatMap { building ->
building.modifiers.mapNotNull { modifier ->
sergeants.find { it.filename.replace(".rgd", "") == modifier.target }?.let {
it.affectedBuildings.add(building)
it
}
}
}
sergeantRepository.saveAll(sergeantsWithBindings)
log.info("Successfully bind buildings to sergeants")
}
private fun bindBuildingToAffectedBuildings(buildings: List<Building>,) {
val buildingsWithBindings: List<Building> = buildings.flatMap { building ->
building.modifiers.mapNotNull { modifier ->
buildings.find { it.filename?.replace(".rgd", "") == modifier.target }?.let {
it.affectedBuildings.add(building)
it
}
}
}
buildingRepository.saveAll(buildingsWithBindings)
log.info("Successfully bind buildings to each other")
}
private fun bindBuildingWeapons(weapons: List<Weapon>, buildings: List<Building>) {
val weaponsWithBindings: List<Weapon> = buildings.flatMap { building ->
building.modifiers.mapNotNull { modifier ->
weapons.find { it.filename?.replace(".rgd", "") == modifier.target }?.let {
it.affectedBuildings.add(building)
it
}
}
}
weaponRepository.saveAll(weaponsWithBindings)
log.info("Successfully bind buildings to weapons")
}
} }

View File

@ -2,9 +2,11 @@ package com.dowstats.service.w40k
import com.dowstats.Metadata import com.dowstats.Metadata
import com.dowstats.data.entities.* import com.dowstats.data.entities.*
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.filterUseless
import com.dowstats.data.entities.addon.AddonModifiers import com.dowstats.data.entities.addon.AddonModifiers
import com.dowstats.data.entities.addon.AddonRequirements import com.dowstats.data.entities.addon.AddonRequirements
import com.dowstats.data.entities.addon.BuildingAddon import com.dowstats.data.entities.addon.BuildingAddon
import com.dowstats.data.entities.building.Building
import com.dowstats.data.rgd.RgdData import com.dowstats.data.rgd.RgdData
import com.dowstats.data.rgd.RgdDataUtil.getBooleanByName import com.dowstats.data.rgd.RgdDataUtil.getBooleanByName
import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName
@ -71,7 +73,7 @@ class BuildingAddonRgdExtractService @Autowired constructor(
} }
} }
} else null } else null
} ?: emptyList() }?.filterUseless() ?: emptyList()
} }
private fun getAddonRequirements(addon: BuildingAddon, addonData: List<RgdData>): List<AddonRequirements> { private fun getAddonRequirements(addon: BuildingAddon, addonData: List<RgdData>): List<AddonRequirements> {

View File

@ -3,6 +3,10 @@ package com.dowstats.service.w40k
import com.dowstats.Metadata import com.dowstats.Metadata
import com.dowstats.data.dto.BuildingDataToSave import com.dowstats.data.dto.BuildingDataToSave
import com.dowstats.data.entities.* import com.dowstats.data.entities.*
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.filterUseless
import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.building.BuildingModifiers
import com.dowstats.data.entities.building.BuildingRequirements
import com.dowstats.data.entities.research.Research import com.dowstats.data.entities.research.Research
import com.dowstats.data.rgd.RgdData import com.dowstats.data.rgd.RgdData
import com.dowstats.data.rgd.RgdDataUtil.getBooleanByName import com.dowstats.data.rgd.RgdDataUtil.getBooleanByName
@ -93,6 +97,8 @@ class BuildingRgdExtractService @Autowired constructor(
building.units = getUnits(buildingData, units).toMutableSet() building.units = getUnits(buildingData, units).toMutableSet()
building.researches = getResearches(buildingData, researches).toMutableSet() building.researches = getResearches(buildingData, researches).toMutableSet()
building.modifiers = getBuildingModifiers(building, buildingData).toMutableSet()
building.buildingRequirements = getBuildingRequirements(building, buildingData).toMutableSet() building.buildingRequirements = getBuildingRequirements(building, buildingData).toMutableSet()
val addons = getAddons(buildingData) val addons = getAddons(buildingData)
@ -209,6 +215,27 @@ class BuildingRgdExtractService @Autowired constructor(
} ?: emptyList() } ?: emptyList()
} }
private fun getBuildingModifiers(building: Building, buildingData: List<RgdData>): List<BuildingModifiers> {
val modifiersData = buildingData.getRgdTableByName("modifier_apply_ext")
val allModifiers = modifiersData?.getRgdTableByName("modifiers").orEmpty() +
modifiersData?.getRgdTableByName("modifiers_idle").orEmpty() +
modifiersData?.getRgdTableByName("modifiers_immediate").orEmpty()
return allModifiers.mapNotNull { m ->
if (m.name.contains("modifier_")) {
val mTable = m.value as List<RgdData>
if (mTable.getStringByName("\$REF") == "modifiers\\no_modifier.lua" || mTable.getStringByName("\$REF") == "modifiers\\enable_infiltration.lua" ) null else {
BuildingModifiers().also {
it.building = building
it.reference = mTable.getStringByName("\$REF")
it.target = mTable.getStringByName("target_type_name")
it.usageType = mTable.getRgdTableByName("usage_type")?.getStringByName("\$REF")
it.value = mTable.getDoubleByName("value")
}
}
} else null
}.filterUseless()
}
private fun getBuildingRequirements(building: Building, buildingData: List<RgdData>): List<BuildingRequirements> { private fun getBuildingRequirements(building: Building, buildingData: List<RgdData>): List<BuildingRequirements> {
val requirements = buildingData.getRgdTableByName("requirement_ext")?.getRgdTableByName("requirements") val requirements = buildingData.getRgdTableByName("requirement_ext")?.getRgdTableByName("requirements")
return requirements?.mapNotNull { r -> return requirements?.mapNotNull { r ->

View File

@ -1,6 +1,8 @@
package com.dowstats.service.w40k package com.dowstats.service.w40k
import com.dowstats.data.entities.* import com.dowstats.data.entities.*
import com.dowstats.data.entities.building.BuildingWeapon
import com.dowstats.data.entities.building.BuildingWeaponKey
import com.dowstats.data.entities.research.Research import com.dowstats.data.entities.research.Research
import com.dowstats.data.repositories.* import com.dowstats.data.repositories.*
import com.dowstats.data.rgd.RgdData import com.dowstats.data.rgd.RgdData

View File

@ -2,6 +2,7 @@ package com.dowstats.service.w40k
import com.dowstats.Metadata import com.dowstats.Metadata
import com.dowstats.data.entities.* import com.dowstats.data.entities.*
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.filterUseless
import com.dowstats.data.entities.research.Research import com.dowstats.data.entities.research.Research
import com.dowstats.data.entities.research.ResearchModifiers import com.dowstats.data.entities.research.ResearchModifiers
import com.dowstats.data.entities.research.ResearchRequirements import com.dowstats.data.entities.research.ResearchRequirements
@ -69,7 +70,7 @@ class ResearchRgdExtractService @Autowired constructor(
} }
} }
} else null } else null
} ?: emptyList() }?.filterUseless() ?: emptyList()
} }
private fun getResearchRequirements(research: Research, researchData: List<RgdData>): List<ResearchRequirements> { private fun getResearchRequirements(research: Research, researchData: List<RgdData>): List<ResearchRequirements> {

View File

@ -77,19 +77,31 @@ class WeaponRgdExtractService @Autowired constructor(
} }
private fun getWeaponRequirements(weapon: Weapon, weaponData: List<RgdData>): List<WeaponRequirements> { private fun getWeaponRequirements(weapon: Weapon, weaponData: List<RgdData>): List<WeaponRequirements> {
val requirements = weaponData.getRgdTableByName("requirements") return try{
return requirements?.mapNotNull { r -> val requirements = weaponData.getRgdTableByName("requirements")
if (r.name.contains("required_")) { requirements?.mapNotNull { r ->
val rTable = r.value as List<RgdData> if (r.name.contains("required_")) {
if (rTable.getStringByName("\$REF") == Metadata.Requirements.REFERENCE_REQUIREMENT_NONE) null else { try {
WeaponRequirements().also { val rTable = r.value as List<RgdData>
it.weapon = weapon if (rTable.getStringByName("\$REF") == Metadata.Requirements.REFERENCE_REQUIREMENT_NONE) null else {
it.reference = rTable.getStringByName("\$REF") WeaponRequirements().also {
it.value = commonParseRgdService.getRequirementReference(it.reference, rTable, weapon.filename!!, log) it.weapon = weapon
it.reference = rTable.getStringByName("\$REF")
it.value = commonParseRgdService.getRequirementReference(it.reference, rTable, weapon.filename!!, log)
}
}
} catch (e: Exception){
log.error("Error parsing requirement ${r.name} weapon ${weapon.name}", e)
null
} }
}
} else null } else null
} ?: emptyList() } ?: emptyList()
} catch (e: Exception){
log.error("Error parsing requirement weapon ${weapon.name}", e)
emptyList()
}
} }

View File

@ -0,0 +1,66 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add building_affected_buildings table",
"author": "anibus",
"changes": [
{
"createTable": {
"tableName": "building_affected_buildings",
"columns": [
{
"column": {
"name": "building_id",
"type": "int",
"constraints": {
"nullable": false
}
}
},
{
"column": {
"name": "building_id_affected",
"type": "int",
"constraints": {
"nullable": false
}
}
}
]
}
},
{
"addUniqueConstraint": {
"columnNames": "building_id, building_id_affected",
"constraintName": "uc_building_affected_buildings_building_id_building_id_affected",
"tableName": "building_affected_buildings"
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "building_id",
"baseTableName": "building_affected_buildings",
"constraintName": "fk_building_affected_buildings_buildings",
"referencedColumnNames": "id",
"referencedTableName": "buildings",
"onDelete": "CASCADE"
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "building_id_affected",
"baseTableName": "building_affected_buildings",
"constraintName": "fk_building_affected_buildings_buildings_2",
"referencedColumnNames": "id",
"referencedTableName": "buildings",
"onDelete": "CASCADE"
}
}
]
}
}
]
}

View File

@ -0,0 +1,66 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add building_affected_sergeants table",
"author": "anibus",
"changes": [
{
"createTable": {
"tableName": "building_affected_sergeants",
"columns": [
{
"column": {
"name": "building_id",
"type": "int",
"constraints": {
"nullable": false
}
}
},
{
"column": {
"name": "sergeant_id",
"type": "int",
"constraints": {
"nullable": false
}
}
}
]
}
},
{
"addUniqueConstraint": {
"columnNames": "building_id, sergeant_id",
"constraintName": "uc_building_affected_sergeants_building_id_sergeant_id",
"tableName": "building_affected_sergeants"
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "building_id",
"baseTableName": "building_affected_sergeants",
"constraintName": "fk_buildings_building_affected_sergeants",
"referencedColumnNames": "id",
"referencedTableName": "buildings",
"onDelete": "CASCADE"
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "sergeant_id",
"baseTableName": "building_affected_sergeants",
"constraintName": "fk_building_affected_sergeants_sergeants",
"referencedColumnNames": "id",
"referencedTableName": "sergeants",
"onDelete": "CASCADE"
}
}
]
}
}
]
}

View File

@ -0,0 +1,66 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add building_affected_units table",
"author": "anibus",
"changes": [
{
"createTable": {
"tableName": "building_affected_units",
"columns": [
{
"column": {
"name": "building_id",
"type": "int",
"constraints": {
"nullable": false
}
}
},
{
"column": {
"name": "unit_id",
"type": "int",
"constraints": {
"nullable": false
}
}
}
]
}
},
{
"addUniqueConstraint": {
"columnNames": "building_id, unit_id",
"constraintName": "uc_buildings_affected_units_building_id_unit_id",
"tableName": "building_affected_units"
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "building_id",
"baseTableName": "building_affected_units",
"constraintName": "fk_buildings_building_affected_units",
"referencedColumnNames": "id",
"referencedTableName": "buildings",
"onDelete": "CASCADE"
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "unit_id",
"baseTableName": "building_affected_units",
"constraintName": "fk_units_building_affected_units",
"referencedColumnNames": "id",
"referencedTableName": "units",
"onDelete": "CASCADE"
}
}
]
}
}
]
}

View File

@ -0,0 +1,66 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add building_affected_weapons table",
"author": "anibus",
"changes": [
{
"createTable": {
"tableName": "building_affected_weapons",
"columns": [
{
"column": {
"name": "building_id",
"type": "int",
"constraints": {
"nullable": false
}
}
},
{
"column": {
"name": "weapon_id",
"type": "int",
"constraints": {
"nullable": false
}
}
}
]
}
},
{
"addUniqueConstraint": {
"columnNames": "building_id, weapon_id",
"constraintName": "uc_building_affected_weapons_building_id_weapon_id",
"tableName": "building_affected_weapons"
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "building_id",
"baseTableName": "building_affected_weapons",
"constraintName": "fk_buildings_buildings_affected_weapons",
"referencedColumnNames": "id",
"referencedTableName": "researches",
"onDelete": "CASCADE"
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "weapon_id",
"baseTableName": "building_affected_weapons",
"constraintName": "fk_weapons_buildings_affected_weapons",
"referencedColumnNames": "id",
"referencedTableName": "weapons",
"onDelete": "CASCADE"
}
}
]
}
}
]
}

View File

@ -0,0 +1,69 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add building_modifiers table",
"author": "anibus",
"changes": [
{
"createTable": {
"tableName": "building_modifiers",
"columns": [
{
"column": {
"name": "id",
"type": "int",
"autoIncrement": true,
"constraints": {
"primaryKey": true,
"nullable": false
}
}
},{
"column": {
"name": "reference",
"type": "varchar(255)"
}
},{
"column": {
"name": "usage_type",
"type": "varchar(255)"
}
},{
"column": {
"name": "value",
"type": "number"
}
},{
"column": {
"name": "target",
"type": "varchar(255)"
}
},{
"column": {
"name": "building_id",
"type": "int",
"constraints": {
"nullable": false
}
}
}
]
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "building_id",
"baseTableName": "building_modifiers",
"constraintName": "fk_building_building_modifiers",
"referencedColumnNames": "id",
"referencedTableName": "buildings",
"onDelete": "CASCADE"
}
}
]
}
}
]
}

View File

@ -159,10 +159,6 @@
"include": { "include": {
"file": "db/0.0.3/data/armor_types.json" "file": "db/0.0.3/data/armor_types.json"
} }
},{
"include": {
"file": "db/0.0.3/procedures/delete_campaign_entities.sql"
}
}, },
{ {
"include": { "include": {
@ -217,6 +213,30 @@
"include": { "include": {
"file": "db/0.0.3/schema/weapons.json" "file": "db/0.0.3/schema/weapons.json"
} }
},{
"include": {
"file": "db/0.0.3/procedures/delete_campaign_entities.sql"
}
},{
"include": {
"file": "db/0.0.3/schema/building_modifiers.json"
}
},{
"include": {
"file": "db/0.0.3/schema/building_affected_units.json"
}
},{
"include": {
"file": "db/0.0.3/schema/building_affected_sergeants.json"
}
},{
"include": {
"file": "db/0.0.3/schema/building_affected_buildings.json"
}
},{
"include": {
"file": "db/0.0.3/schema/building_affected_weapons.json"
}
} }
] ]
} }

View File

@ -20,8 +20,8 @@ class ModDiffPrinter {
val rgdService = RgdService() val rgdService = RgdService()
val prevVersion = "Dowstats_Balance_Mod_1_0_97" val prevVersion = "wanila"
val currentVersion = "Dowstats_Balance_Mod_1_0_98" val currentVersion = "Definitive_Edition2.1.1"
val spaceMarinesPath = "space_marines" val spaceMarinesPath = "space_marines"
val chaosPath = "chaos" val chaosPath = "chaos"
@ -47,10 +47,10 @@ class ModDiffPrinter {
} }
} }
fun getUnitsAndSquadsDiff(out: PrintWriter) { private fun getUnitsAndSquadsDiff(out: PrintWriter) {
racesWikiPaths.forEach{racePath -> racesWikiPaths.forEach{racePath ->
val rgdDataOld = File("src/main/resources/static/mods/$prevVersion/attrib/sbps/races/$racePath").walkTopDown().map { val rgdDataOld = File("D:/home/cnb/mods/$prevVersion/Data/attrib/sbps/races/$racePath").walkTopDown().map {
val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){ val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){
rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream())) rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream()))
} else { } else {
@ -60,7 +60,7 @@ class ModDiffPrinter {
}.filter { it.second != null } }.filter { it.second != null }
.toMap() .toMap()
val rgdDataNew = File("src/main/resources/static/mods/$currentVersion/attrib/sbps/races/$racePath").walkTopDown().map { val rgdDataNew = File("D:/home/cnb/mods/$currentVersion/Data/attrib/sbps/races/$racePath").walkTopDown().map {
val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){ val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){
rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream())) rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream()))
}else{ }else{
@ -71,7 +71,7 @@ class ModDiffPrinter {
.sortedBy { it.first } .sortedBy { it.first }
.toMap() .toMap()
val rgdDataUnitsOld = File("src/main/resources/static/mods/$prevVersion/attrib/ebps/races/$racePath/troops").walkTopDown().map { val rgdDataUnitsOld = File("D:/home/cnb/mods/$prevVersion/Data/attrib/ebps/races/$racePath/troops").walkTopDown().map {
val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){ val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){
rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream())) rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream()))
}else{ }else{
@ -81,7 +81,7 @@ class ModDiffPrinter {
}.filter { it.second != null } }.filter { it.second != null }
.toMap() .toMap()
val rgdDataUnitsNew = File("src/main/resources/static/mods/$currentVersion/attrib/ebps/races/$racePath/troops").walkTopDown().map { val rgdDataUnitsNew = File("D:/home/cnb/mods/$currentVersion/Data/attrib/ebps/races/$racePath/troops").walkTopDown().map {
val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){ val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){
rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream())) rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream()))
}else{ }else{
@ -124,7 +124,7 @@ class ModDiffPrinter {
fun getAllWeaponsDiff(out: PrintWriter) { fun getAllWeaponsDiff(out: PrintWriter) {
val wanillaRgdData = File("src/main/resources/static/mods/wanila/attrib/weapon").walkTopDown().map { val wanillaRgdData = File("D:/home/cnb/wanila/attrib/weapon").walkTopDown().map {
val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){ val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){
rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream())) rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream()))
} else { } else {
@ -134,7 +134,7 @@ class ModDiffPrinter {
}.filter { it.second != null } }.filter { it.second != null }
.toMap() .toMap()
val classicRgdData = File("src/main/resources/static/mods/$prevVersion/attrib/weapon").walkTopDown().map { val classicRgdData = File("D:/home/cnb/mods/$prevVersion/Data/attrib/weapon").walkTopDown().map {
val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){ val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){
rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream())) rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream()))
} else { } else {
@ -144,7 +144,7 @@ class ModDiffPrinter {
}.filter { it.second != null } }.filter { it.second != null }
.toMap() .toMap()
val newRgdData = File("src/main/resources/static/mods/$currentVersion/attrib/weapon").walkTopDown().map { val newRgdData = File("D:/home/cnb/mods/$currentVersion/Data/attrib/weapon").walkTopDown().map {
val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){ val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){
rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream())) rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream()))
} else { } else {
@ -176,7 +176,7 @@ class ModDiffPrinter {
return racesWikiPaths.map{racePath -> return racesWikiPaths.map{racePath ->
val rgdData42 = File("src/main/resources/static/mods/$currentVersion/attrib/sbps/races/$racePath").walkTopDown().map { val rgdData42 = File("D:/home/cnb/mods/$currentVersion/Data/attrib/sbps/races/$racePath").walkTopDown().map {
val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){ val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){
rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream())) rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream()))
}else{ }else{
@ -186,7 +186,7 @@ class ModDiffPrinter {
}.filter { it.second != null } }.filter { it.second != null }
.toMap() .toMap()
val newUnits = File("src/main/resources/static/mods/$currentVersion/attrib/ebps/races/$racePath/troops").walkTopDown().map { val newUnits = File("D:/home/cnb/mods/$currentVersion/Data/attrib/ebps/races/$racePath/troops").walkTopDown().map {
val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){ val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){
rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream())) rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream()))
}else{ }else{
@ -211,7 +211,7 @@ class ModDiffPrinter {
fun getWeaponRgdMap(): Map<String, List<RgdData>?> { fun getWeaponRgdMap(): Map<String, List<RgdData>?> {
return File("src/main/resources/static/mods/$currentVersion/attrib/weapon").walkTopDown().map { return File("D:/home/cnb/mods/$currentVersion/Data/attrib/weapon").walkTopDown().map {
val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){ val rgdData = if(it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")){
rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream())) rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream()))
} else { } else {
@ -287,12 +287,11 @@ class ModDiffPrinter {
} }
@Test private fun getAllBuildingsDiff(out: PrintWriter) {
fun getAllBuildingsDiff(out: PrintWriter) {
racesWikiPaths.forEach { racePath -> racesWikiPaths.forEach { racePath ->
val classicRgdData = val classicRgdData =
File("src/main/resources/static/mods/$prevVersion/attrib/ebps/races/$racePath/structures").walkTopDown().map { File("D:/home/cnb/mods/$prevVersion/Data/attrib/ebps/races/$racePath/structures").walkTopDown().map {
val rgdData = if (it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")) { val rgdData = if (it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")) {
rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream())) rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream()))
} else { } else {
@ -302,7 +301,7 @@ class ModDiffPrinter {
}.filter { it.second != null } }.filter { it.second != null }
.toMap() .toMap()
val newRgdData = File("src/main/resources/static/mods/$currentVersion/attrib/ebps/races/$racePath/structures").walkTopDown().map { val newRgdData = File("D:/home/cnb/mods/$currentVersion/Data/attrib/ebps/races/$racePath/structures").walkTopDown().map {
val rgdData = if (it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")) { val rgdData = if (it.isFile && !it.name.contains("hg_dxp3") && !it.name.contains("npc")) {
rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream())) rgdParseService.parseRgdFileStream(DataInputStream(it.inputStream()))
} else { } else {
@ -324,11 +323,6 @@ class ModDiffPrinter {
} }
} }
@Test
fun saveAllDataToDb() {
// modParserService.saveModDataToDb()
}
@Test @Test
fun getAllDiffAndPrintToFiles(){ fun getAllDiffAndPrintToFiles(){
val weaponDiffFileName = "$prevVersion-$currentVersion-weapons.txt" val weaponDiffFileName = "$prevVersion-$currentVersion-weapons.txt"