Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Q
quality-kpi
Manage
Activity
Members
Labels
Plan
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Quiring, Ole
quality-kpi
Commits
41cbe8fd
Commit
41cbe8fd
authored
2 years ago
by
Hock, Benedikt
Browse files
Options
Downloads
Patches
Plain Diff
Checked some TODOs
parent
ef0fc4d4
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
functions/lego_classes.py
+150
-55
150 additions, 55 deletions
functions/lego_classes.py
with
150 additions
and
55 deletions
functions/lego_classes.py
+
150
−
55
View file @
41cbe8fd
...
@@ -2,97 +2,192 @@
...
@@ -2,97 +2,192 @@
File consists of several classes for the different elements of a device.
File consists of several classes for the different elements of a device.
'''
'''
from
__future__
import
annotations
from
__future__
import
annotations
from
enum
import
Enum
,
auto
import
uuid
import
uuid
from
typing
import
Any
,
Union
,
Literal
,
TypedDict
,
TypeVar
,
Type
,
List
,
Optional
,
Dict
from
typing
import
Any
,
Union
,
Literal
,
TypedDict
,
TypeVar
,
Type
,
List
,
Optional
,
Dict
import
json
# TODO
# TODO
# - Parents direkt setzen
# - Alle gemeinsamen JSON attribute im LegoItem constructor
# - enforce uuid
# - Docstrings
# - Docstrings
# - Beschreibung von Teilen (-> properties)
# - Beschreibung von Teilen (-> properties)
# - Gute String Darstellung
# - Gute String Darstellung
# - Minimalbeispiel für KPIs
# - Minimalbeispiel für KPIs
# - Klassen analog zur deutschen Aufgabenstellung umbenennen (assembly, component) #13 #17
# - Export als JSON
# - Export als GraphViz
# - Export als GraphViz
# - AggregationsEbene enum (system, assembly, subassembly, component)
class
LegoItem
:
class
ComponentCategory
(
Enum
):
def
__init__
(
self
,
item_number
:
int
,
mass
:
float
,
delivery_time
:
int
,
**
kwargs
)
->
None
:
BATTERY
=
auto
()
# , *args, **kwargs not handling additional/optional specs right now
MOTOR
=
auto
()
self
.
id
:
uuid
.
UUID
=
uuid
.
uuid4
()
FRAME
=
auto
()
self
.
properties
:
dict
=
kwargs
WHEEL
=
auto
()
self
.
item_number
:
int
=
item_number
AXLE
=
auto
()
GEAR
=
auto
()
class
AggregationLayer
(
Enum
):
SYSTEM
=
auto
()
ASSEMBLY
=
auto
()
SUBASSEMBLY
=
auto
()
COMPONENT
=
auto
()
class
LegoComponent
:
def
__init__
(
self
,
name
:
str
,
category
:
ComponentCategory
,
lego_id
:
str
,
cost
:
float
,
mass
:
float
,
delivery_time
:
int
,
layer
:
AggregationLayer
=
AggregationLayer
.
COMPONENT
,
**
properties
)
->
None
:
self
.
uuid
:
uuid
.
UUID
=
uuid
.
uuid4
()
self
.
parent
:
None
|
LegoAssembly
=
None
self
.
name
:
str
=
name
self
.
category
:
ComponentCategory
=
category
self
.
lego_id
:
str
=
lego_id
self
.
cost
:
float
=
cost
self
.
mass
:
float
=
mass
self
.
mass
:
float
=
mass
self
.
delivery_time
:
int
=
delivery_time
self
.
delivery_time
:
int
=
delivery_time
# TODO: Set parent directly and not via id? This would allow for easier traversal of the tree
self
.
layer
:
AggregationLayer
=
layer
# Currently there is no way to search for parts and components in tree by id.
self
.
properties
:
dict
=
properties
self
.
parent_id
=
None
# This will be set when added to a component
def
clone
(
self
)
->
LegoComponent
:
clone
=
LegoComponent
(
self
.
name
,
self
.
category
,
self
.
lego_id
,
self
.
cost
,
self
.
mass
,
self
.
delivery_time
,
self
.
layer
,
**
self
.
properties
)
return
clone
def
get_root_assembly
(
self
):
if
self
.
parent
is
None
:
return
None
current_assembly
=
self
.
parent
while
current_assembly
.
parent
is
not
None
:
current_assembly
=
current_assembly
.
parent
return
current_assembly
def
to_dict
(
self
)
->
Dict
:
ATTRIBUTES
=
[
"
uuid
"
,
"
name
"
,
"
category
"
,
"
lego_id
"
,
"
cost
"
,
"
mass
"
,
"
delivery_time
"
,
"
layer
"
,
"
properties
"
]
dict_
=
{}
# store attributes
for
attr
in
ATTRIBUTES
:
dict_
[
attr
]
=
getattr
(
self
,
attr
)
dict_
=
{
"
component
"
:
dict_
}
return
dict_
# TODO good string representation
def
__str__
(
self
):
def
__str__
(
self
):
return
self
.
__repr__
()
return
(
return
(
f
"
Item(id=
{
self
.
id
}
, item_number=
{
self
.
item_number
}
,
"
f
"
Item(id=
{
self
.
uu
id
}
, item_number=
{
self
.
lego_id
}
,
"
f
"
mass=
{
self
.
mass
}
, delivery_time=
{
self
.
delivery_time
}
,
"
f
"
mass=
{
self
.
mass
}
, delivery_time=
{
self
.
delivery_time
}
,
"
f
"
parent_id=
{
self
.
parent
_id
}
)
"
f
"
parent_id=
{
self
.
parent
}
)
"
)
)
# TODO good repr representation
def
__repr__
(
self
):
def
__repr__
(
self
):
return
f
"
Lego
Item
[
{
self
.
id
}
]
"
return
f
"
Lego
Component
{
self
.
name
}
[
{
self
.
uu
id
}
]
"
class
LegoComponent
:
class
LegoAssembly
:
def
__init__
(
self
,
**
kwargs
)
->
None
:
def
__init__
(
self
,
name
:
str
,
layer
:
AggregationLayer
,
**
properties
)
->
None
:
self
.
id
:
uuid
.
UUID
=
uuid
.
uuid4
()
self
.
uuid
:
uuid
.
UUID
=
uuid
.
uuid4
()
self
.
properties
:
dict
=
kwargs
self
.
parent
:
None
|
LegoAssembly
=
None
self
.
items
:
List
[
LegoItem
]
=
[]
self
.
name
:
str
=
name
self
.
layer
:
AggregationLayer
=
layer
self
.
properties
:
dict
=
properties
self
.
components
:
List
[
LegoComponent
]
=
[]
self
.
components
:
List
[
LegoComponent
]
=
[]
self
.
parent_id
:
None
|
uuid
.
UUID
=
None
self
.
assemblies
:
List
[
LegoAssembly
]
=
[]
def
add_item
(
self
,
item
:
LegoItem
)
->
None
:
if
not
isinstance
(
item
,
LegoItem
):
raise
TypeError
(
f
"'
item
'
should be of type LegoPart, got
{
type
(
item
).
__name__
}
instead.
"
)
item
.
parent_id
=
self
.
id
self
.
items
.
append
(
item
)
def
add_component
(
self
,
component
:
LegoComponent
)
->
None
:
def
add_component
(
self
,
component
:
LegoComponent
)
->
None
:
if
not
isinstance
(
component
,
LegoComponent
):
if
not
isinstance
(
component
,
LegoComponent
):
raise
TypeError
(
f
"'
component
'
should be of type LegoComponent, got
{
type
(
component
).
__name__
}
instead.
"
)
raise
TypeError
(
f
"
Argument should be of type
{
LegoComponent
.
__name__
}
,
"
component
.
parent_id
=
self
.
id
f
"
got
{
type
(
component
).
__name__
}
instead.
"
)
if
self
.
get_root_assembly
().
contains_uuid
(
component
.
uuid
):
raise
AssertionError
(
f
"
This assembly or a subassembly already contains the component with ID
"
f
"
{
component
.
uuid
}
.
"
)
component
.
parent
=
self
self
.
components
.
append
(
component
)
self
.
components
.
append
(
component
)
def
children
(
self
)
->
Dict
[
str
,
List
[
LegoItem
]
|
List
[
LegoComponent
]]:
def
add_assembly
(
self
,
assembly
:
LegoAssembly
)
->
None
:
return
{
'
items
'
:
self
.
items
,
'
components
'
:
self
.
components
}
if
not
isinstance
(
assembly
,
LegoAssembly
):
raise
TypeError
(
f
"
Argument should be of type
{
LegoAssembly
.
__name__
}
,
"
f
"
got
{
type
(
assembly
).
__name__
}
instead.
"
)
if
self
.
get_root_assembly
().
contains_uuid
(
assembly
.
uuid
):
raise
AssertionError
(
f
"
This assembly or a subassembly already contains the assembly with ID
"
f
"
{
assembly
.
uuid
}
.
"
)
assembly
.
parent
=
self
self
.
assemblies
.
append
(
assembly
)
def
children
(
self
)
->
Dict
[
str
,
List
[
LegoComponent
]
|
List
[
LegoAssembly
]]:
return
{
'
components
'
:
self
.
components
,
'
assemblies
'
:
self
.
assemblies
}
def
get_component_list
(
self
,
max_depth
:
int
=
-
1
)
->
List
[
LegoComponent
]:
component_list
=
[]
component_list
.
extend
(
self
.
components
)
if
max_depth
>
0
:
for
assembly
in
self
.
assemblies
:
component_list
.
extend
(
assembly
.
get_component_list
(
max_depth
-
1
))
return
component_list
def
get_item_list
(
self
)
->
List
[
LegoItem
]:
def
get_root_assembly
(
self
)
->
LegoAssembly
:
item_list
=
[]
current_assembly
=
self
item_list
.
extend
(
self
.
items
)
while
current_assembly
.
parent
is
not
None
:
for
component
in
self
.
components
:
current_assembly
=
current_assembly
.
parent
item_list
.
extend
(
component
.
get_item_list
())
return
current_assembly
return
item_list
def
contains_uuid
(
self
,
uuid_
:
uuid
.
UUID
):
# check component ids
component_ids
=
list
(
map
(
lambda
c
:
c
.
uuid
,
self
.
components
))
if
uuid_
in
component_ids
:
return
True
# check assembly ids
assembly_ids
=
list
(
map
(
lambda
a
:
a
.
uuid
,
self
.
assemblies
))
if
uuid_
in
assembly_ids
:
return
True
# recursively check assemblies
for
assembly
in
self
.
assemblies
:
if
assembly
.
contains_uuid
(
uuid_
):
return
True
return
False
def
to_dict
(
self
)
->
Dict
:
ATTRIBUTES
=
[
"
uuid
"
,
"
name
"
,
"
layer
"
,
"
properties
"
]
dict_
=
{}
# store attributes
for
attr
in
ATTRIBUTES
:
dict_
[
attr
]
=
getattr
(
self
,
attr
)
# store components
dict_
[
"
components
"
]
=
[
component
.
to_dict
()
for
component
in
self
.
components
]
dict_
[
"
assemblies
"
]
=
[
assembly
.
to_dict
()
for
assembly
in
self
.
assemblies
]
return
{
"
assembly
"
:
dict_
}
# TODO find good string representation
def
__repr__
(
self
):
def
__repr__
(
self
):
return
f
"
Lego
Component
[
{
self
.
id
}
]
"
return
f
"
Lego
Assembly
{
self
.
name
}
[
{
self
.
uu
id
}
]
"
# TODO: Adjust default output when printing an item or component
def
print_
component
_tree
(
root
,
level
=
0
,
is_last
=
False
):
def
print_
assembly
_tree
(
root
,
level
=
0
,
is_last
=
False
):
# print component
# print component
component
_padding
=
""
assembly
_padding
=
""
if
level
>
0
:
if
level
>
0
:
component
_padding
+=
"
│
"
*
(
level
-
1
)
assembly
_padding
+=
"
│
"
*
(
level
-
1
)
if
is_last
:
if
is_last
:
component
_padding
+=
"
└──
"
assembly
_padding
+=
"
└──
"
else
:
else
:
component
_padding
+=
"
├──
"
assembly
_padding
+=
"
├──
"
print
(
f
"
{
component
_padding
}{
root
}
"
)
print
(
f
"
{
assembly
_padding
}{
root
}
"
)
# recursively print child components
# recursively print child components
for
i
,
component
in
enumerate
(
root
.
component
s
):
for
i
,
assembly
in
enumerate
(
root
.
assemblie
s
):
is_last_
=
i
==
len
(
root
.
component
s
)
-
1
and
len
(
root
.
item
s
)
==
0
is_last_
=
i
==
len
(
root
.
assemblie
s
)
-
1
and
len
(
root
.
component
s
)
==
0
print_
component_tree
(
component
,
level
+
1
,
is_last_
)
print_
assembly_tree
(
assembly
,
level
+
1
,
is_last_
)
# print items
# print items
for
i
,
item
in
enumerate
(
root
.
items
):
for
i
,
item
in
enumerate
(
root
.
components
):
item_padding
=
"
│
"
*
level
component_padding
=
"
│
"
*
level
if
not
is_last
else
"
"
item_padding
+=
"
├──
"
if
i
<
len
(
root
.
items
)
-
1
else
"
└──
"
component_padding
+=
"
├──
"
if
i
<
len
(
root
.
components
)
-
1
else
"
└──
"
print
(
f
"
{
item_padding
}{
item
}
"
)
print
(
f
"
{
component_padding
}{
item
}
"
)
class
KPIEncoder
(
json
.
JSONEncoder
):
def
default
(
self
,
o
):
if
isinstance
(
o
,
uuid
.
UUID
):
return
"
kpi-
"
+
str
(
o
)
if
isinstance
(
o
,
(
ComponentCategory
,
AggregationLayer
)):
return
"
kpi-
"
+
o
.
name
return
super
().
default
(
o
)
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment