new ground objects format & parser; place dead objects instead of removing them completely

This commit is contained in:
Vasyl Horbachenko 2018-09-12 05:19:21 +03:00
parent 6fb342a42c
commit 03fc17fae6
7 changed files with 106 additions and 99 deletions

View File

@ -100,18 +100,13 @@ class Event:
for object_identifier in debriefing.destroyed_objects: for object_identifier in debriefing.destroyed_objects:
for cp in self.game.theater.controlpoints: for cp in self.game.theater.controlpoints:
remove_ids = []
if not cp.ground_objects: if not cp.ground_objects:
continue continue
for i, ground_object in enumerate(cp.ground_objects): for i, ground_object in enumerate(cp.ground_objects):
if ground_object.matches_string_identifier(object_identifier): if ground_object.matches_string_identifier(object_identifier):
logging.info("cp {} removing ground object {}".format(cp, ground_object.string_identifier)) logging.info("cp {} killing ground object {}".format(cp, ground_object.string_identifier))
remove_ids.append(i) ground_object.is_dead = True
remove_ids.reverse()
for i in remove_ids:
del cp.ground_objects[i]
def skip(self): def skip(self):
pass pass

View File

@ -10,17 +10,6 @@ from dcs.statics import *
FARP_FRONTLINE_DISTANCE = 10000 FARP_FRONTLINE_DISTANCE = 10000
CATEGORY_MAPPING = {
"power": [Fortification.Workshop_A],
"warehouse": [Warehouse.Warehouse],
"fuel": [Warehouse.Tank],
"ammo": [Warehouse.Ammunition_depot],
"farp": [Fortification.FARP_Tent],
"comms": [Fortification.TV_tower],
"oil": [Fortification.Oil_platform],
}
class GroundObjectsGenerator: class GroundObjectsGenerator:
FARP_CAPACITY = 4 FARP_CAPACITY = 4
@ -53,7 +42,10 @@ class GroundObjectsGenerator:
cp = self.conflict.from_cp cp = self.conflict.from_cp
for ground_object in cp.ground_objects: for ground_object in cp.ground_objects:
if ground_object.category == "defense": if ground_object.dcs_identifier == "AA":
if ground_object.is_dead:
continue
unit_type = random.choice(self.game.commision_unit_types(cp, AirDefence)) unit_type = random.choice(self.game.commision_unit_types(cp, AirDefence))
assert unit_type is not None, "Cannot find unit type for GroundObject defense ({})!".format(cp) assert unit_type is not None, "Cannot find unit type for GroundObject defense ({})!".format(cp)
@ -62,17 +54,23 @@ class GroundObjectsGenerator:
name=ground_object.string_identifier, name=ground_object.string_identifier,
_type=unit_type, _type=unit_type,
position=ground_object.position, position=ground_object.position,
heading=ground_object.heading heading=ground_object.heading,
) )
logging.info("generated defense object identifier {} with mission id {}".format(group.name, group.id)) logging.info("generated defense object identifier {} with mission id {}".format(group.name, group.id))
else: else:
if ground_object.dcs_identifier in warehouse_map:
static_type = warehouse_map[ground_object.dcs_identifier]
else:
static_type = fortification_map[ground_object.dcs_identifier]
group = self.m.static_group( group = self.m.static_group(
country=side, country=side,
name=ground_object.string_identifier, name=ground_object.string_identifier,
_type=random.choice(CATEGORY_MAPPING[ground_object.category]), _type=static_type,
position=ground_object.position, position=ground_object.position,
heading=ground_object.heading heading=ground_object.heading,
dead=ground_object.is_dead,
) )
logging.info("generated object identifier {} with mission id {}".format(group.name, group.id)) logging.info("generated object identifier {} with mission id {}".format(group.name, group.id))

Binary file not shown.

View File

@ -1,86 +1,87 @@
import pickle import pickle
import typing import typing
from game import db
from gen.groundobjectsgen import TheaterGroundObject
from dcs.mission import Mission from dcs.mission import Mission
from dcs.mapping import Point from dcs.mapping import Point
from dcs.unitgroup import VehicleGroup, StaticGroup
from dcs.unit import *
from dcs.statics import warehouse_map, fortification_map
from game import db
from gen.groundobjectsgen import TheaterGroundObject
m = Mission() m = Mission()
m.load_file("./cau_groundobjects.miz") m.load_file("./cau_groundobjects.miz")
result = {}
result_by_groups = {} # type: typing.Dict[int, TheaterGroundObject] def parse_name(name: str) -> int:
cp_counters = {} first_part = name.split()[0].split("|")
ids_counters = {} return int(first_part[0]) if len(first_part) == 1 else int(first_part[1])
group_id_counter = 0
previous_group_id = None
def append_group(cp_id, category, group_id, object_id, position, heading): if __name__ == "__main__":
global result theater_objects = []
global result_by_groups
ground_object = TheaterGroundObject(category, cp_id, group_id, object_id, position, heading) for group in m.country("Russia").static_group + m.country("Russia").vehicle_group:
for unit in group.units:
theater_object = TheaterGroundObject()
theater_object.object_id = len(theater_objects) + 1
if cp_id not in result: try:
result[cp_id] = [] theater_object.cp_id = parse_name(str(unit.name))
result[cp_id].append(ground_object) except Exception as e:
theater_object.cp_id = parse_name(str(group.name))
result_by_groups_key = "{}_{}_{}".format(cp_id, category, group_id) theater_object.position = unit.position
if result_by_groups_key not in result_by_groups: theater_object.heading = unit.heading
result_by_groups[result_by_groups_key] = []
result_by_groups[result_by_groups_key].append(ground_object)
if isinstance(unit, Vehicle):
theater_object.dcs_identifier = "AA"
else:
theater_object.dcs_identifier = unit.type
def parse_name(name: str) -> typing.Tuple: airport_distance = m.terrain.airport_by_id(theater_object.cp_id).position.distance_to_point(theater_object.position)
args = str(name.split()[0]).split("|") if airport_distance > 150000:
print("Object {} {} is placed {}m from airport {}!".format(theater_object.dcs_identifier,
group.name,
airport_distance,
m.terrain.airport_by_id(theater_object.cp_id)))
if len(args) == 2: assert theater_object.dcs_identifier
global group_id_counter assert theater_object.cp_id
group_id_counter += 1 assert theater_object.object_id
args.append(str(group_id_counter))
else:
global previous_group_id
if previous_group_id != args[2]:
group_id_counter += 1
previous_group_id = args[2]
return args[0], int(args[1]), int(args[2]) theater_objects.append(theater_object)
group_ids = 1
for object_a in theater_objects:
for object_b in theater_objects:
if object_a.position.distance_to_point(object_b.position) < 2000:
if object_a.group_id and object_b.group_id:
continue
elif object_a.group_id:
object_b.group_id = object_a.group_id
elif object_b.group_id:
object_a.group_id = object_b.group_id
else:
object_a.group_id = group_ids
object_b.group_id = group_ids
group_ids += 1
for group in m.country("Russia").static_group + m.country("Russia").vehicle_group: assert object_a.cp_id == object_b.cp_id, "Object {} and {} are placed in group with different airports!".format(object_a.string_identifier, object_b.string_identifier)
try:
category, cp_id, group_id = parse_name(str(group.name))
except:
print("Failed to parse {}".format(group.name))
continue
ids_counters_key = "{}_{}".format(cp_id, group_id) for a in theater_objects:
ids_counters[ids_counters_key] = ids_counters.get(ids_counters_key, 0) + 1 if not a.group_id:
object_id = ids_counters[ids_counters_key] a.group_id = group_ids
cp_counters[cp_id] = cp_counters.get(cp_id, 0) + 1 group_ids += 1
append_group(cp_id, category, group_id, object_id, group.position, group.units[0].heading) print("Total {} objects".format(len(theater_objects)))
with open("../cau_groundobjects.p", "wb") as f:
result = {}
for theater_object in theater_objects:
if theater_object.cp_id not in result:
result[theater_object.cp_id] = []
result[theater_object.cp_id].append(theater_object)
GROUP_TRESHOLD = 2000 pickle.dump(result, f)
did_check_pairs = []
for group_id, objects_in_group in result_by_groups.items():
for a in objects_in_group:
for b in objects_in_group:
if (a, b) in did_check_pairs:
continue
did_check_pairs.append((a, b))
distance = a.position.distance_to_point(b.position)
if distance > GROUP_TRESHOLD:
print("Objects {} and {} in group {} are too far apart ({})!".format(a.string_identifier, b.string_identifier, group_id, distance))
print("Total {} objects".format(sum([len(x) for x in result.values()])))
for cp_id, count in cp_counters.items():
print("{} - {} objects".format(cp_id, count))
with open("../cau_groundobjects.p", "wb") as f:
pickle.dump(result, f)

View File

@ -6,7 +6,7 @@ NAME_BY_CATEGORY = {
"power": "Power plant", "power": "Power plant",
"ammo": "Ammo depot", "ammo": "Ammo depot",
"fuel": "Fuel depot", "fuel": "Fuel depot",
"defense": "AA Defense Site", "aa": "AA Defense Site",
"warehouse": "Warehouse", "warehouse": "Warehouse",
"farp": "FARP", "farp": "FARP",
"comms": "Comms. tower", "comms": "Comms. tower",
@ -17,7 +17,7 @@ ABBREV_NAME = {
"power": "PLANT", "power": "PLANT",
"ammo": "AMMO", "ammo": "AMMO",
"fuel": "FUEL", "fuel": "FUEL",
"defense": "AA", "aa": "AA",
"warehouse": "WARE", "warehouse": "WARE",
"farp": "FARP", "farp": "FARP",
"comms": "COMMST", "comms": "COMMST",
@ -25,21 +25,35 @@ ABBREV_NAME = {
} }
CATEGORY_MAP = {
"aa": ["AA"],
"power": ["Workshop A"],
"warehouse": ["Warehouse"],
"fuel": ["Tank"],
"ammo": [".Ammunition depot"],
"farp": ["FARP Tent"],
"comms": ["TV tower", "Comms tower"],
"oil": ["Oil platform"],
}
class TheaterGroundObject: class TheaterGroundObject:
object_id = 0
cp_id = 0 cp_id = 0
group_id = 0 group_id = 0
object_id = 0
dcs_identifier = None # type: str
is_dead = False
heading = 0 heading = 0
position = None # type: Point position = None # type: Point
category = None # type: str
def __init__(self, category, cp_id, group_id, object_id, position, heading): @property
self.category = category def category(self) -> str:
self.cp_id = cp_id for k, v in CATEGORY_MAP.items():
self.group_id = group_id if self.dcs_identifier in v:
self.object_id = object_id return k
self.position = position assert False, "Identifier not found in mapping: {}".format(self.dcs_identifier)
self.heading = heading
@property @property
def string_identifier(self): def string_identifier(self):

View File

@ -17,6 +17,7 @@ from dcs.unit import UnitType
from game import db from game import db
from .persistency import base_path from .persistency import base_path
from theater.theatergroundobject import CATEGORY_MAP
DEBRIEFING_LOG_EXTENSION = "log" DEBRIEFING_LOG_EXTENSION = "log"
@ -123,10 +124,9 @@ class Debriefing:
for event in events.values(): for event in events.values():
event_type = event.get("type", None) event_type = event.get("type", None)
if event_type in ["crash", "dead"]: if event_type in ["crash", "dead"]:
object_initiator = event["initiator"] in ["SKLAD_CRUSH", "SKLADCDESTR", "TEC_A_CRUSH", "BAK_CRUSH"] initiator_components = event["initiator"].split("|")
defense_initiator = event["initiator"].startswith("defense|")
if object_initiator or defense_initiator: if initiator_components[0] in CATEGORY_MAP:
parse_dead_object(event) parse_dead_object(event)
else: else:
parse_dead_unit(event) parse_dead_unit(event)
@ -138,7 +138,6 @@ class Debriefing:
result = {} result = {}
for group in groups: for group in groups:
for unit in group.units: for unit in group.units:
unit_type = None
if isinstance(unit, Vehicle): if isinstance(unit, Vehicle):
unit_type = vehicle_map[unit.type] unit_type = vehicle_map[unit.type]
elif isinstance(unit, Ship): elif isinstance(unit, Ship):