Page Menu
Home
Wildfire Games
Search
Configure Global Search
Log In
Paste
P267
Fix D4584.
Active
Public
Actions
Authored by
Freagarach
on Mar 14 2022, 7:55 AM.
Edit Paste
Archive Paste
View Raw File
Subscribe
Mute Notifications
Award Token
Flag For Later
Tags
None
Subscribers
None
#!/usr/bin/env python3
from
lxml
import
etree
as
ET
import
fileinput
import
glob
import
json
import
os
import
pysvn
import
sys
class
StyleFixer
:
def
fix_template_style
(
template_path
):
changes
=
[
[
"version='1.0'"
,
'version="1.0"'
],
[
"'UTF-8'"
,
'"utf-8"'
]
]
StyleFixer
.
sed
(
template_path
,
changes
)
def
sed
(
path
,
changes
):
for
line
in
fileinput
.
input
(
path
,
inplace
=
True
):
for
change
in
changes
:
line
=
line
.
replace
(
change
[
0
],
change
[
1
])
print
(
line
,
end
=
""
)
def
simplify_requirements
(
reqs
):
if
len
(
reqs
)
!=
1
:
return
all_req
=
reqs
.
find
(
"All"
)
if
all_req
==
None
:
return
reqs
.
remove
(
all_req
)
for
child
in
all_req
:
reqs
.
append
(
child
)
def
sort_xml
(
node
):
node
[:]
=
sorted
(
node
,
key
=
lambda
child
:
child
.
tag
)
for
child
in
node
:
StyleFixer
.
sort_xml
(
child
)
class
TechnologyConverter
:
def
__init__
(
self
,
vfs_root
):
self
.
scc
=
pysvn
.
Client
()
self
.
tech_folder
=
os
.
path
.
join
(
vfs_root
,
'simulation'
,
'data'
,
'technologies'
)
self
.
template_folder
=
os
.
path
.
join
(
vfs_root
,
'simulation'
,
'templates'
)
self
.
tech_template_folder
=
os
.
path
.
join
(
self
.
template_folder
,
'technologies'
)
self
.
civs
=
[]
os
.
makedirs
(
self
.
tech_template_folder
,
exist_ok
=
True
)
self
.
scc
.
add
(
self
.
tech_template_folder
,
force
=
True
)
with
os
.
scandir
(
os
.
path
.
join
(
self
.
template_folder
,
'special'
,
'players'
))
as
civ_files
:
for
civ_file
in
civ_files
:
if
civ_file
.
is_file
():
civ
=
civ_file
.
name
.
removesuffix
(
".xml"
)
if
civ
==
'gaia'
:
continue
self
.
civs
.
append
(
civ
)
civ_folder
=
os
.
path
.
join
(
self
.
tech_template_folder
,
civ
)
os
.
makedirs
(
civ_folder
,
exist_ok
=
True
)
self
.
scc
.
add
(
civ_folder
,
force
=
True
)
def
add_requirements
(
self
,
req_json
,
reqs
):
if
'tech'
in
req_json
:
ET
.
SubElement
(
reqs
,
"Techs"
)
.
text
=
req_json
[
'tech'
]
if
'entity'
in
req_json
:
ent_req
=
ET
.
SubElement
(
ET
.
SubElement
(
reqs
,
"Entities"
),
req_json
[
'entity'
][
'class'
])
if
'number'
in
req_json
[
'entity'
]:
ET
.
SubElement
(
ent_req
,
"Number"
)
.
text
=
str
(
req_json
[
'entity'
][
'number'
])
if
'variants'
in
req_json
[
'entity'
]:
ET
.
SubElement
(
ent_req
,
"Variants"
)
.
text
=
str
(
req_json
[
'entity'
][
'variants'
])
if
'all'
in
req_json
:
all_req
=
ET
.
SubElement
(
reqs
,
"All"
)
for
req
in
req_json
[
'all'
]:
self
.
add_requirements
(
req
,
all_req
)
if
len
(
all_req
)
==
0
:
reqs
.
remove
(
all_req
)
if
'any'
in
req_json
:
any_req
=
ET
.
SubElement
(
reqs
,
"Any"
)
for
req
in
req_json
[
'any'
]:
self
.
add_requirements
(
req
,
any_req
)
if
len
(
any_req
)
==
0
:
reqs
.
remove
(
any_req
)
def
add_modifications
(
self
,
cmp_tech
,
tech_json
):
mods
=
ET
.
SubElement
(
cmp_tech
,
"Modifiers"
)
i
=
1
for
mod
in
tech_json
[
'modifications'
]:
modifier
=
ET
.
SubElement
(
mods
,
"modifier"
+
str
(
i
))
ET
.
SubElement
(
modifier
,
"Paths"
)
.
text
=
mod
[
'value'
]
if
'add'
in
mod
:
ET
.
SubElement
(
modifier
,
"Add"
)
.
text
=
str
(
mod
[
'add'
])
elif
'multiply'
in
mod
:
ET
.
SubElement
(
modifier
,
"Multiply"
)
.
text
=
str
(
mod
[
'multiply'
])
elif
'replace'
in
mod
:
ET
.
SubElement
(
modifier
,
"Replace"
)
.
text
=
str
(
mod
[
'replace'
])
if
'affects'
in
tech_json
:
affects
=
ET
.
SubElement
(
modifier
,
"Affects"
)
affects
.
set
(
"datatype"
,
"tokens"
)
affects
.
text
=
tech_json
[
'affects'
][
0
]
for
affect
in
tech_json
[
'affects'
][
1
:]:
affects
.
text
=
affects
.
text
+
" "
+
affect
if
'affects'
in
modifier
:
for
affect
in
modifier
[
'affects'
]:
affects
.
text
=
affects
.
text
+
" "
+
affect
def
create_civ_tech
(
self
,
tech_json
,
name
,
civ
):
file_path
=
os
.
path
.
join
(
self
.
tech_template_folder
,
civ
,
name
)
+
".xml"
root
=
ET
.
Element
(
"Technology"
)
root
.
set
(
"parent"
,
"technologies/"
+
name
)
cmp_identity
=
ET
.
SubElement
(
root
,
"Identity"
)
ET
.
SubElement
(
cmp_identity
,
"Civ"
)
.
text
=
civ
if
'specificName'
in
tech_json
and
civ
in
tech_json
[
'specificName'
]:
ET
.
SubElement
(
cmp_identity
,
"SpecificName"
)
.
text
=
tech_json
[
'specificName'
][
civ
]
StyleFixer
.
sort_xml
(
root
)
ET
.
ElementTree
(
root
)
.
write
(
file_path
,
xml_declaration
=
True
,
pretty_print
=
True
,
encoding
=
'utf-8'
)
StyleFixer
.
fix_template_style
(
file_path
)
self
.
scc
.
add
(
file_path
)
def
convert_tech_to_template
(
self
,
tech_path
,
name
):
tech_json
=
json
.
load
(
tech_path
)
root
=
ET
.
Element
(
"Technology"
)
cmp_tech
=
ET
.
SubElement
(
root
,
"Technology"
)
ET
.
SubElement
(
cmp_tech
,
"ID"
)
.
text
=
name
if
'top'
in
tech_json
:
ET
.
SubElement
(
cmp_tech
,
"Choice"
)
.
text
=
"technologies/{civ}/"
+
tech_json
[
'top'
]
+
" "
+
"technologies/{civ}/"
+
tech_json
[
'bottom'
]
cmp_identity
=
ET
.
SubElement
(
root
,
"Identity"
)
ET
.
SubElement
(
cmp_identity
,
"GenericName"
)
.
text
=
tech_json
[
'genericName'
]
ET
.
SubElement
(
cmp_identity
,
"History"
)
.
text
=
tech_json
[
'description'
]
if
'description'
in
tech_json
else
""
ET
.
SubElement
(
cmp_identity
,
"Icon"
)
.
text
=
tech_json
[
'icon'
]
ET
.
SubElement
(
cmp_identity
,
"Tooltip"
)
.
text
=
tech_json
[
'tooltip'
]
# The identity spec requires this.
ET
.
SubElement
(
cmp_identity
,
"Undeletable"
)
.
text
=
"true"
# It would be nice to not have this dual relationship.
if
'pair'
in
tech_json
:
ET
.
SubElement
(
cmp_tech
,
"ChoiceRoot"
)
.
text
=
tech_json
[
'pair'
]
if
'phase'
in
name
:
classes
=
ET
.
SubElement
(
cmp_identity
,
"Classes"
)
classes
.
set
(
"datatype"
,
"tokens"
)
classes
.
text
=
"Phase"
if
'supersedes'
in
tech_json
:
ET
.
SubElement
(
cmp_tech
,
"Supersedes"
)
.
text
=
"technologies/{civ}/"
+
tech_json
[
'supersedes'
]
if
'autoResearch'
in
tech_json
:
ET
.
SubElement
(
cmp_tech
,
"AutoResearched"
)
allowed_civs
=
[]
disallowed_civs
=
[]
if
'requirements'
in
tech_json
:
reqs
=
ET
.
Element
(
"Requirements"
)
self
.
add_requirements
(
tech_json
[
'requirements'
],
reqs
)
if
'all'
in
tech_json
[
'requirements'
]:
for
req
in
tech_json
[
'requirements'
][
'all'
]:
if
'civ'
in
req
:
allowed_civs
.
append
(
req
[
'civ'
])
if
'notciv'
in
req
:
disallowed_civs
.
append
(
req
[
'notciv'
])
if
'any'
in
req
:
for
civ_req
in
req
[
'any'
]:
allowed_civs
.
append
(
civ_req
[
'civ'
])
elif
'any'
in
tech_json
[
'requirements'
]:
for
req
in
tech_json
[
'requirements'
][
'any'
]:
if
'civ'
in
req
:
allowed_civs
.
append
(
req
[
'civ'
])
elif
'civ'
in
tech_json
[
'requirements'
]:
allowed_civs
.
append
(
tech_json
[
'requirements'
][
'civ'
])
StyleFixer
.
simplify_requirements
(
reqs
)
if
'requirementsTooltip'
in
tech_json
:
techs
=
reqs
.
find
(
'Techs'
)
if
len
(
reqs
)
!=
1
or
techs
==
None
:
ET
.
SubElement
(
reqs
,
"Tooltip"
)
.
text
=
tech_json
[
'requirementsTooltip'
]
if
len
(
reqs
)
>
0
:
cmp_identity
.
append
(
reqs
)
if
'cost'
in
tech_json
:
cmp_cost
=
ET
.
SubElement
(
root
,
"Cost"
)
for
element
in
tech_json
[
'cost'
]:
ET
.
SubElement
(
cmp_cost
,
element
)
.
text
=
str
(
tech_json
[
'cost'
][
element
])
if
'researchTime'
in
tech_json
:
ET
.
SubElement
(
cmp_cost
,
"BuildTime"
)
.
text
=
str
(
tech_json
[
'researchTime'
])
if
'soundComplete'
in
tech_json
:
ET
.
SubElement
(
ET
.
SubElement
(
root
,
"Sound"
),
"completed"
)
.
text
=
tech_json
[
'soundComplete'
]
if
'modifications'
in
tech_json
:
self
.
add_modifications
(
cmp_tech
,
tech_json
)
if
len
(
allowed_civs
)
>
0
and
len
(
disallowed_civs
)
>
0
:
print
(
"Warning: complex (dis)allowed civs: "
+
name
)
if
len
(
disallowed_civs
)
>
0
:
for
civ
in
self
.
civs
:
if
not
civ
in
disallowed_civs
:
allowed_civs
.
append
(
civ
)
elif
len
(
allowed_civs
)
==
0
:
allowed_civs
=
self
.
civs
[:]
if
len
(
allowed_civs
)
==
1
:
civ
=
allowed_civs
[
0
]
ET
.
SubElement
(
cmp_identity
,
"Civ"
)
.
text
=
civ
if
'specificName'
in
tech_json
and
civ
in
tech_json
[
'specificName'
]:
ET
.
SubElement
(
cmp_identity
,
"SpecificName"
)
.
text
=
tech_json
[
'specificName'
][
civ
]
else
:
for
civ
in
allowed_civs
:
self
.
create_civ_tech
(
tech_json
,
name
,
civ
)
StyleFixer
.
sort_xml
(
root
)
ET
.
ElementTree
(
root
)
.
write
(
tech_path
.
name
,
xml_declaration
=
True
,
pretty_print
=
True
,
encoding
=
'utf-8'
)
return
allowed_civs
def
run
(
self
):
for
tech_path
in
glob
.
iglob
(
self
.
tech_folder
+
'/*.json'
,
recursive
=
True
):
name
=
os
.
path
.
basename
(
tech_path
)
.
removesuffix
(
".json"
)
if
'phase'
in
name
:
if
'generic'
in
name
:
name
=
name
.
removesuffix
(
"_generic"
)
else
:
continue
tech_template_path
=
os
.
path
.
join
(
self
.
tech_template_folder
,
name
)
+
".xml"
self
.
scc
.
move
(
tech_path
,
tech_template_path
)
with
open
(
tech_template_path
,
'r'
)
as
file
:
try
:
allowed_civs
=
self
.
convert_tech_to_template
(
file
,
name
)
except
Exception
as
e
:
print
(
"Error: Failed conversion: "
+
name
)
print
(
e
)
StyleFixer
.
fix_template_style
(
tech_template_path
)
if
len
(
allowed_civs
)
==
1
:
self
.
scc
.
move
(
tech_template_path
,
os
.
path
.
join
(
self
.
tech_template_folder
,
allowed_civs
[
0
],
name
)
+
".xml"
)
def
convert_input_file
(
self
,
relative_path
):
new_path
=
relative_path
if
'json'
in
relative_path
:
new_path
=
relative_path
.
removesuffix
(
".json"
)
+
".xml"
self
.
scc
.
move
(
relative_path
,
new_path
)
name
=
os
.
path
.
basename
(
new_path
)
.
removesuffix
(
".xml"
)
with
open
(
new_path
,
'r'
)
as
file
:
try
:
self
.
convert_tech_to_template
(
file
,
name
)
except
Exception
as
e
:
print
(
"Error: Failed conversion: "
+
relative_path
)
print
(
e
)
StyleFixer
.
fix_template_style
(
new_path
)
class
TemplateFixer
:
def
__init__
(
self
,
vfs_root
):
self
.
template_folder
=
os
.
path
.
join
(
vfs_root
,
'simulation'
,
'templates'
)
def
fix_template
(
self
,
template_path
):
tree
=
ET
.
parse
(
template_path
)
root
=
tree
.
getroot
()
cmp_researcher
=
root
.
find
(
'Researcher'
)
if
cmp_researcher
==
None
:
return
False
technologies
=
cmp_researcher
.
find
(
'Technologies'
)
if
technologies
==
None
:
return
False
new_names
=
[]
for
technology
in
technologies
.
text
.
split
():
prefix
=
"technologies/{civ}/"
if
prefix
in
technology
:
new_names
.
append
(
technology
.
removesuffix
(
"_{civ}"
))
else
:
new_names
.
append
(
prefix
+
technology
.
removesuffix
(
"_{civ}"
))
technologies
.
text
=
"
\n
"
+
'
\n
'
.
join
(
sorted
(
new_names
))
+
"
\n
"
tree
.
write
(
template_path
,
xml_declaration
=
True
,
pretty_print
=
True
,
encoding
=
'utf-8'
)
return
True
def
run
(
self
):
for
template_path
in
glob
.
iglob
(
self
.
template_folder
+
'/*.xml'
,
recursive
=
True
):
if
self
.
fix_template
(
template_path
):
StyleFixer
.
fix_template_style
(
template_path
)
if
__name__
==
'__main__'
:
script_dir
=
os
.
path
.
dirname
(
os
.
path
.
realpath
(
__file__
))
tech_converter
=
TechnologyConverter
(
script_dir
)
if
len
(
sys
.
argv
)
>
1
:
for
tech_path
in
sys
.
argv
[
1
:]:
tech_converter
.
convert_input_file
(
tech_path
)
else
:
tech_converter
.
run
()
template_fixer
=
TemplateFixer
(
script_dir
)
template_fixer
.
run
()
Event Timeline
Freagarach
created this paste.
Mar 14 2022, 7:55 AM
Freagarach
created this object with visibility "No One".
Freagarach
edited the content of this paste.
(Show Details)
Mar 14 2022, 5:18 PM
Freagarach
edited the content of this paste.
(Show Details)
Mar 25 2022, 4:46 PM
Freagarach
mentioned this in
D4584: [WIP] - Technologies to templates.
.
Mar 31 2022, 8:24 AM
Freagarach
changed the title of this paste from
Fix Dxxxx.
to
Fix D4584.
.
Mar 31 2022, 8:24 AM
Freagarach
edited the content of this paste.
(Show Details)
Freagarach
changed the visibility from "No One" to "Public (No Login Required)".
Freagarach
edited the content of this paste.
(Show Details)
Apr 1 2022, 5:51 PM
Freagarach
edited the content of this paste.
(Show Details)
Apr 9 2022, 9:35 AM
Freagarach
edited the content of this paste.
(Show Details)
Apr 17 2022, 7:16 AM
Freagarach
edited the content of this paste.
(Show Details)
Nov 25 2022, 8:47 AM
Log In to Comment