Compare commits

..

5 Commits

Author SHA1 Message Date
Ivan
0149f98c8b F: Add schemas coloring option for TermGraph
Some checks failed
Backend CI / build (3.12) (push) Has been cancelled
Frontend CI / build (22.x) (push) Has been cancelled
2024-09-14 17:11:26 +03:00
Ivan
d33f3e02b4 B: Fix buttons layers 2024-09-14 16:13:51 +03:00
Ivan
3555db3edf R: Add inherited cst source to API 2024-09-14 15:14:48 +03:00
Ivan
fc669b8b3a M: Shorten manuals landing page 2024-09-13 13:31:03 +03:00
Ivan
495493bbbb B: Fix incorrect local variable index parsing 2024-09-13 12:17:39 +03:00
32 changed files with 275 additions and 184 deletions

View File

@ -58,7 +58,6 @@ class TestChangeAttributes(EndpointTester):
self.operation3.refresh_from_db()
self.ks3 = RSForm(self.operation3.result)
@decl_endpoint('/api/library/{item}/set-owner', method='patch')
def test_set_owner(self):
data = {'user': self.user3.pk}

View File

@ -57,6 +57,33 @@ class TestChangeConstituents(EndpointTester):
self.ks3 = RSForm(self.operation3.result)
self.assertEqual(self.ks3.constituents().count(), 4)
@decl_endpoint('/api/rsforms/{item}/details', method='get')
def test_retrieve_inheritance(self):
response = self.executeOK(item=self.ks3.model.pk)
self.assertEqual(response.data['oss'], [{'id': self.owned.model.pk, 'alias': 'T1'}])
self.assertEqual(response.data['inheritance'], [
{
'child': Constituenta.objects.get(as_child__parent_id=self.ks1X1.pk).pk,
'child_source': self.ks3.model.pk,
'parent': self.ks1X1.pk, 'parent_source': self.ks1.model.pk
},
{
'child': Constituenta.objects.get(as_child__parent_id=self.ks1X2.pk).pk,
'child_source': self.ks3.model.pk,
'parent': self.ks1X2.pk, 'parent_source': self.ks1.model.pk
},
{
'child': Constituenta.objects.get(as_child__parent_id=self.ks2X1.pk).pk,
'child_source': self.ks3.model.pk,
'parent': self.ks2X1.pk, 'parent_source': self.ks2.model.pk
},
{
'child': Constituenta.objects.get(as_child__parent_id=self.ks2D1.pk).pk,
'child_source': self.ks3.model.pk,
'parent': self.ks2D1.pk, 'parent_source': self.ks2.model.pk
},
])
@decl_endpoint('/api/rsforms/{schema}/create-cst', method='post')
def test_create_constituenta(self):
data = {

View File

@ -4,6 +4,7 @@ from .basics import (
ASTNodeSerializer,
ExpressionParseSerializer,
ExpressionSerializer,
InheritanceDataSerializer,
MultiFormSerializer,
ResolverSerializer,
TextSerializer,

View File

@ -122,6 +122,14 @@ class ReferenceSerializer(serializers.Serializer):
pos_output = TextPositionSerializer()
class InheritanceDataSerializer(serializers.Serializer):
''' Serializer: inheritance data. '''
child = serializers.IntegerField()
child_source = serializers.IntegerField()
parent = serializers.IntegerField() # type: ignore
parent_source = serializers.IntegerField()
class ResolverSerializer(serializers.Serializer):
''' Serializer: Resolver results serializer. '''
input = serializers.CharField()

View File

@ -17,7 +17,7 @@ from apps.oss.models import Inheritance
from shared import messages as msg
from ..models import Constituenta, CstType, RSForm
from .basics import CstParseSerializer
from .basics import CstParseSerializer, InheritanceDataSerializer
from .io_pyconcept import PyConceptAdapter
@ -103,7 +103,7 @@ class RSFormSerializer(serializers.ModelSerializer):
child=CstSerializer()
)
inheritance = serializers.ListField(
child=serializers.ListField(child=serializers.IntegerField())
child=InheritanceDataSerializer()
)
oss = serializers.ListField(
child=LibraryItemReferenceSerializer()
@ -116,8 +116,17 @@ class RSFormSerializer(serializers.ModelSerializer):
def to_representation(self, instance: LibraryItem) -> dict:
result = self.to_base_data(instance)
for link in Inheritance.objects.filter(Q(child__schema=instance) | Q(parent__schema=instance)):
result['inheritance'].append([link.child.pk, link.parent.pk])
inheritances = Inheritance.objects \
.filter(Q(child__schema=instance) | Q(parent__schema=instance)) \
.select_related('parent__schema', 'child__schema') \
.only('parent__id', 'parent__schema__id', 'child__id', 'child__schema__id')
for link in inheritances:
result['inheritance'].append({
'child': link.child_id,
'child_source': link.child.schema_id,
'parent': link.parent_id,
'parent_source': link.parent.schema_id
})
return result
def to_base_data(self, instance: LibraryItem) -> dict:

View File

@ -1,7 +1,6 @@
import { styleTags, tags } from '@lezer/highlight';
export const highlighting = styleTags({
'Index': tags.unit,
'ComplexIndex': tags.unit,
'Literal': tags.literal,

View File

@ -2,15 +2,14 @@
export const
Expression = 1,
Local = 2,
Index = 3,
Literal = 5,
Global = 6,
Radical = 7,
Filter = 20,
ComplexIndex = 21,
PrefixD = 26,
PrefixI = 27,
PrefixR = 29,
Function = 31,
TextFunction = 32,
Predicate = 45
Literal = 4,
Global = 5,
Radical = 6,
Filter = 19,
ComplexIndex = 20,
PrefixD = 25,
PrefixI = 26,
PrefixR = 28,
Function = 30,
TextFunction = 31,
Predicate = 44

View File

@ -3,7 +3,7 @@ import { printTree } from '@/utils/codemirror';
import { parser } from './parser';
const testData = [
['a1', '[Expression[Local[Index]]]'],
['a1', '[Expression[Local]]'],
['A1', '[Expression[Global]]'],
['∅', '[Expression[Literal]]'],
['Z', '[Expression[Literal]]'],
@ -15,7 +15,7 @@ const testData = [
['¬2=2', '[Expression[¬][Literal][=][Literal]]'],
['12+41', '[Expression[Literal][+][Literal]]'],
['1+2*5', '[Expression[Literal][+][Literal][*][Literal]]'],
['a1Z', '[Expression[Local[Index]][][Literal]]'],
['a1Z', '[Expression[Local][][Literal]]'],
['Pr1(X1)', '[Expression[TextFunction[ComplexIndex]][(][Global][)]]'],
['Pr11(X1)', '[Expression[TextFunction[ComplexIndex]][(][Global][)]]'],
['Pr11,21(X1)', '[Expression[TextFunction[ComplexIndex]][(][Global][)]]'],
@ -41,8 +41,9 @@ const testData = [
['∀ξ∈∅ 1=1', '[Expression[∀][Local][∈][Literal][Literal][=][Literal]]'],
[
'∀ξ1∈β (ξ1≠∅ & ∀ξ2∈β ξ1∩ξ2=∅)',
'[Expression[∀][Local[Index]][∈][Local][(][Local[Index]][≠][Literal][&][∀][Local[Index]][∈][Local][Local[Index]][∩][Local[Index]][=][Literal][)]]'
]
'[Expression[∀][Local][∈][Local][(][Local][≠][Literal][&][∀][Local][∈][Local][Local][∩][Local][=][Literal][)]]'
],
['∀α1∈α2 1=1', '[Expression[∀][Local][∈][Local][Literal][=][Literal]]']
];
describe('Testing RSParser', () => {

View File

@ -3,16 +3,16 @@ import {LRParser} from "@lezer/lr"
import {highlighting} from "./highlight"
export const parser = LRParser.deserialize({
version: 14,
states: "5lO!sQPOOO!zQPO'#C^OOQO'#Ca'#CaO%uQPO'#DqOOQO'#Dq'#DqO(SQPO'#DeOVQPO'#DrO(ZQPO'#DtO)kQPO'#DuO)sQQO'#DvO)xQPO'#DwO)}QPO'#DxO*SQPO'#DzOOQO'#Ds'#DsO*XQPO'#DsO+uQQO'#C|OOQO'#C|'#C|OOQO'#Dn'#DnO+zQPO'#DnO,PQPO'#DnO,UQPO'#DgOVQPO'#ESO,^QPO'#ESO,cQPO'#ESO,kQPO'#DeOOQO'#Df'#DfO,fQPO'#EVQOQPOOOOQO'#C_'#C_OOQO,58x,58xO(ZQPO,5:^O(ZQPO,5:^O(ZQPO,5:^O(ZQPO,5:^O(ZQPO,5:^O(ZQPO,5:^O(ZQPO,5:^O(ZQPO,5:^O(ZQPO,5:RO,|QPO'#DmO-TQPO,5:^O.hQPO,5:VO.pQPO'#DlO.uQPO,5:QO/WQPO,5:cO/yQPO'#DmO(ZQPO'#DrO0WQPO,5:`OOQO'#Dm'#DmO(ZQPO,5:aOOQO,5:a,5:aO0`QPO,5:bO,cQPO,5:cO(ZQPO,5:dO,cQPO,5:fOOQO,59h,59hO(ZQPO,5:YO(ZQPO,5:YO&uQPO'#DgOOQO,5:n,5:nO(ZQPO,5:nO(ZQPO'#DkOOQO'#Dh'#DhOOQO'#ET'#ETO0eQPO,5:nOVQPO,5:pOVQPO,5:pOVQPO,5:pOVQPO,5:pO0mQPO'#EXOOQO'#EW'#EWO0rQPO,5:qOOQO1G/x1G/xO2wQPO1G/xO3OQPO1G/xO5SQPO1G/xO7WQPO1G/xO7_QPO1G/xO7fQPO1G/xO8OQPO1G/xO9qQPO1G/mOOQO1G/q1G/qO(ZQPO,5:WOOQO1G/l1G/lO(ZQPO1G/}OOQO1G/z1G/zO:bQPO1G/{O(ZQPO1G/|O:iQPO1G/}O:nQPO1G0OO:uQPO1G0QO:zQPO1G/tO;SQPO1G/tO;ZQPO1G0YO,cQPO,5:oO;cQPO1G0YOOQO1G0[1G0[O=_QPO1G0[O=fQPO1G0[O=mQPO1G0[O(ZQPO,5:sO,fQPO,5:rOVQPO1G0]O>[QPO1G/rO>lQPO7+%iOOQO7+%g7+%gO>sQPO7+%hO(ZQPO7+%iOVQPO7+%jO(ZQPO7+%lOOQO7+%`7+%`OOQO7+%t7+%tOOQO1G0Z1G0ZOOQO'#C^'#C^O>{QPO7+%tO?iQPO1G0_OOQO1G0^1G0^OOQO7+%w7+%wOVQPO<<ITO?sQPO<<ISO?xQPO<<ITO@PQPO'#DyO@eQPO<<IUO@mQPO<<IWO@tQPO<<I`OAcQPOAN>oO(ZQPOAN>nOVQPOAN>oOVQPO,5:eOOQOAN>pAN>pOVQPOAN>rOOQOG24ZG24ZOAtQPOG24YOA{QPOG24ZOB^QPO1G0POBrQPOG24^OByQPOG24^OOQOLD)tLD)tOOQOLD)uLD)uOOQOLD)xLD)xO(ZQPOLD)xOC[QPO!$'MdOOQO!)9CO!)9COO;cQPO,5:^O;cQPO,5:^O;cQPO,5:^O;cQPO,5:^O;cQPO,5:^O;cQPO,5:^O;cQPO,5:^O;cQPO,5:^OCcQPO1G/xOE[QPO1G/xOIWQPO1G/xOKbQPO1G/xOKiQPO1G/xOKpQPO1G/xOKwQPO1G/x",
stateData: "NR~O!WOS~OSUOUSOVSOaVOcWOdXOjYOkZOm[OobO|eO}fO!OgO!PgO!]PO!^QO!cQO!dQO!o_O!p_O!q`O!r`O!s`O!t`O~OfjO~PVO!^lOWQXXQXYQXZQX[QX]QX^QX_QXhQXnQXqQXrQXsQXtQXuQXvQXwQXxQXyQXzQX{QX!UQX!uQXbQX!QQX!RQX!SQX!TQX`QXiQXgQXlQX~OW!eXX!eXY!eXZ!eX[!eX]!eX^!eX_!eX!u!eXb!eX~Oh!eXn![Xq![Xr!eXs!eXt!eXu!eXv!eXw!eXx!eXy!eXz!eX{!eX!U!eX~P%TOWnOXoOYpOZqO[rO]sO^tO_uOhvOrvOsvOtvOuvOvvOwvOxvOyvOzvO{vO~O!U!XX~P&uOS!OOUSOVSOaVOcWOdXOjYOkZOm[OobO!]PO!^QO!cQO!dQO!o_O!p_O!q`O!r`O!s`O!t`O~OS!ROcWO~Oe!TO~Oa!UO~Oa!VO~Oa!WO~OW!gXX!gXY!gXZ!gX[!gX]!gX^!gX_!gXh!gXn![Xq![Xr!gXs!gXt!gXu!gXv!gXw!gXx!gXy!gXz!gX{!gX!U!gX!u!gXb!gX~Oe!XO~Of!YO~OS!ZO~OnvOqvO~Of!^O~OS!_O!]PO~O!Q!cO!R!dO!S!eO!T!fO!U!XX~O!u!aX~P&uO`!jOW!bXX!bXY!bXZ!bX[!bX]!bX^!bX_!bXh!bXr!bXs!bXt!bXu!bXv!bXw!bXx!bXy!bXz!bX{!bX!u!bX~O`!sO!u!aX~O!u!tO~O`!uO!Q!cO!R!dO!S!eO!T!fO~Oh!vO~P%TOWnOXoOYpOZqO[rO]sO^tO_uO~Ob!aX!u!aXg!aX~P/_Ob!wO!u!tO~Of!yO~Oh#RO!u#QO~Oh#WO~Og#YO!u#XO~OWnOY!fiZ!fi[!fi]!fi^!fi_!fih!fir!fis!fit!fiu!fiv!fiw!fix!fiy!fiz!fi{!fi!U!fi`!fi!u!fib!fi!Q!fi!R!fi!S!fi!T!fii!fig!fil!fi~OX!fi~P0zOXoO~P0zOWnOXoOYpO_uO[!fi]!fi^!fih!fir!fis!fit!fiu!fiv!fiw!fix!fiy!fiz!fi{!fi!U!fi`!fi!u!fib!fi!Q!fi!R!fi!S!fi!T!fii!fig!fil!fi~OZ!fi~P3VOWnOXoOYpOZqO^tO_uO]!fih!fir!fis!fit!fiu!fiv!fiw!fix!fiy!fiz!fi{!fi!U!fi`!fi!u!fib!fi!Q!fi!R!fi!S!fi!T!fii!fig!fil!fi~O[!fi~P5ZO[rO~P5ZOZqO~P3VOZ!fi[!fi]!fi^!fi_!fi~OWnOXoOYpOh!fir!fis!fit!fiu!fiv!fiw!fix!fiy!fiz!fi{!fi!U!fi`!fi!u!fib!fi!Q!fi!R!fi!S!fi!T!fii!fig!fil!fi~P7mO!Q!Zi!R!Zi!S!Zi!T!Zi!U!Zi`!Zib!Zil!Zii!Zi~P/_O`#]O~P/_Oh#_O~Oi#`O~P/_On#aO~Og#bO!u!tO~O`#bO~P/_Og#cO!u!tO~OS!OOUSOVSOaVOcWOdXOjYOkZOm[OobO!]#eO!^QO!cQO!dQO!o_O!p_O!q`O!r`O!s`O!t`O~O!Q!cO!S!xi!T!xi!U!xi`!xib!xil!xii!xi~O!R!xi~P<sO!R!dO~P<sO!Q!cO!R!dO!S!eO!T!xi!U!xi`!xib!xil!xii!xi~O`!`i!u!`ib!`ig!`i~P/_Oi#jO~P/_Og#kO!u!tO~OW$TOX$UOY$VOZ$WO[$XO]$YO^$ZO_$[O~PVOg!{i!u!{i~P/_OS#rO~Oi#sO~P/_O!Q!cO!R!dO!S!eO!T!fOb!mXl!mX~Ob#uOl#tO~Oi#vO~P/_O!Q!cO!R!dO!S!eO!T!fO!U!vy`!vyb!vyl!vyi!vy~Ob#wO!Q!cO!R!dO!S!eO!T!fO~O`#}O~P/_Ob$OO!Q!cO!R!dO!S!eO!T!fO~O!Q!cO!R!dO!S!eO!T!fOb!mil!mi~Ob$PO~P&uOi$QO!Q!cO!R!dO!S!eO!T!fO~Ob$SO~P/_OW$TOS!fiU!fiV!fiX!fiY!fia!fic!fid!fij!fik!fim!fio!fi|!fi}!fi!O!fi!P!fi!]!fi!^!fi!c!fi!d!fi!o!fi!p!fi!q!fi!r!fi!s!fi!t!fi~P7mOW$TOX$UOS!fiU!fiV!fiY!fia!fic!fid!fij!fik!fim!fio!fi|!fi}!fi!O!fi!P!fi!]!fi!^!fi!c!fi!d!fi!o!fi!p!fi!q!fi!r!fi!s!fi!t!fi~P7mOW$TOX$UOY$VO_$[OS!fiU!fiV!fi[!fi]!fi^!fia!fic!fid!fij!fik!fim!fio!fi|!fi}!fi!O!fi!P!fi!]!fi!^!fi!c!fi!d!fi!o!fi!p!fi!q!fi!r!fi!s!fi!t!fi~OZ!fi~PGTOW$TOX$UOY$VOZ$WO^$ZO_$[OS!fiU!fiV!fi]!fia!fic!fid!fij!fik!fim!fio!fi|!fi}!fi!O!fi!P!fi!]!fi!^!fi!c!fi!d!fi!o!fi!p!fi!q!fi!r!fi!s!fi!t!fi~O[!fi~PI_O[$XO~PI_OZ$WO~PGTOW$TOX$UOY$VOS!fiU!fiV!fia!fic!fid!fij!fik!fim!fio!fi|!fi}!fi!O!fi!P!fi!]!fi!^!fi!c!fi!d!fi!o!fi!p!fi!q!fi!r!fi!s!fi!t!fi~P7mOd!o}oUV!q!r!s!t!p!]mkjk~",
goto: "0m!|PP!}$aP$dPPPPPPPPPPPPPPPPPPPPPPPPPP%hPPPPPPPPPPPPPPPPPPPPPP&l&r'l'|PP(j)v*R*dPP$d,x$d.O/S.O.O.O0Z.OPPPPPPP'l0^'l0a0d0glROUe!c!d!e!f#Y#`#f#j#s#t#v!dSnopqrstuv!O!R!V!Y!Z!^!_!t!v!y#R#W#_#a#r$Q$T$U$V$W$X$Y$Z$[Q|VW!`g!U!W#QT!gj#XRmP#TaOUVenopqrstuv!O!R!V!Y!Z!^!_!c!d!e!f!t!v!y#R#W#Y#_#`#a#f#j#r#s#t#v$Q$T$U$V$W$X$Y$Z$[#TcOUVenopqrstuv!O!R!V!Y!Z!^!_!c!d!e!f!t!v!y#R#W#Y#_#`#a#f#j#r#s#t#v$Q$T$U$V$W$X$Y$Z$[QkOR#i#YShO#YQ{UQ!]eQ#S!cQ#T!dQ#U!eQ#V!fQ#m#`Q#p#fQ#q#jQ#y#sQ#z#tR#|#vmiOUe!c!d!e!f#Y#`#f#j#s#t#vldOUe!c!d!e!f#Y#`#f#j#s#t#vQ!agQ!z!UQ!|!WR#d#Q!f]Vnopqrstuv!O!R!V!Y!Z!^!_!t!v!y#R#W#_#a#r$Q$T$U$V$W$X$Y$Z$[l^OUe!c!d!e!f#Y#`#f#j#s#t#vX!`g!U!W#QUyU!O!_X!QV!Y!^!yUzU!O!_Q!PVQ!}!YQ#P!^R#^!ySTO#YQwU[}V!O!Y!^!_!yd![e!c!d!e!f#`#f#j#s#tS!jn$TQ!koQ!lpQ!mqQ!nrQ!osQ!ptQ!quQ!rvQ!x!RQ!{!VQ#O!ZQ#Z!tQ#[!vQ#f#RQ#g#WQ#l#_Q#o#aQ#x#rQ#{#vQ$R$QQ$]$UQ$^$VQ$_$WQ$`$XQ$a$YQ$b$ZR$c$[#OaOVenopqrstuv!R!V!Y!Z!^!_!c!d!e!f!t!v!y#R#W#Y#_#`#a#f#j#r#s#t#v$Q$T$U$V$W$X$Y$Z$[TxU!O#T]OUVenopqrstuv!O!R!V!Y!Z!^!_!c!d!e!f!t!v!y#R#W#Y#_#`#a#f#j#r#s#t#v$Q$T$U$V$W$X$Y$Z$[#S]OUVenopqrstuv!O!R!V!Y!Z!^!_!c!d!e!f!t!v!y#R#W#Y#_#`#a#f#j#r#s#t#v$Q$T$U$V$W$X$Y$Z$[R!SWR#n#`R!bgRkOR!ijQ!hjR#h#X",
nodeNames: "⚠ Expression Local Index ( Literal Global Radical + - * \\ ∆ ∩ × ) { } Filter ComplexIndex [ ] ∈ | PrefixD PrefixI ; PrefixR := Function TextFunction :∈ ∉ ⊆ ⊄ ⊂ > ≥ < ≤ ≠ = ¬ Predicate ∀ ∃ ⇔ ⇒ &",
maxTerm: 89,
states: "3UO!sQPOOOOQO'#C`'#C`O#lQPO'#DoOOQO'#Do'#DoO%yQPO'#DdOVQPO'#DpO'_QPO'#DrO'fQPO'#DsO'nQQO'#DtO'sQPO'#DuO'xQPO'#DvO'}QPO'#DxOOQO'#Dq'#DqO(SQPO'#DqO)pQQO'#C{OOQO'#C{'#C{OOQO'#Dk'#DkO)uQPO'#DkO)zQPO'#DkO*PQPO'#DfOVQPO'#EQO*XQPO'#EQO*^QPO'#EQO*fQPO'#DdOOQO'#De'#DeO*wQPO'#ETQOQPOOO*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:QO+TQPO'#DjO+[QPO,5:[O,oQPO,5:SO,wQPO'#DiO,|QPO,5:PO-_QPO,5:aO.QQPO'#DjO*|QPO'#DpO._QPO,5:^OOQO'#Dj'#DjO*|QPO,5:_OOQO,5:_,5:_O.gQPO,5:`O*^QPO,5:aO*|QPO,5:bO*^QPO,5:dOOQO,59g,59gO*|QPO,5:VO*|QPO,5:VO$lQPO'#DfOOQO,5:l,5:lO*|QPO,5:lO*|QPO'#DhOOQO'#Dg'#DgOOQO'#ER'#ERO.lQPO,5:lOVQPO,5:nOVQPO,5:nOVQPO,5:nOVQPO,5:nO.tQPO'#EVOOQO'#EU'#EUO.yQPO,5:oOOQO1G/v1G/vO2jQPO1G/vO2qQPO1G/vO6aQPO1G/vO:PQPO1G/vO:WQPO1G/vO:_QPO1G/vO:fQPO1G/vO>QQPO1G/lOOQO1G/n1G/nO*|QPO,5:TOOQO1G/k1G/kO*|QPO1G/{OOQO1G/x1G/xO>qQPO1G/yO*|QPO1G/zO>xQPO1G/{O>}QPO1G/|O?UQPO1G0OO?ZQPO1G/qO?cQPO1G/qO?jQPO1G0WO*^QPO,5:mO*|QPO1G0WOOQO1G0Y1G0YO@^QPO1G0YO@eQPO1G0YO@lQPO1G0YO*|QPO,5:qO*wQPO,5:pOVQPO1G0ZOAZQPO1G/oOAkQPO7+%gOOQO7+%e7+%eOArQPO7+%fO*|QPO7+%gOVQPO7+%hO*|QPO7+%jOOQO7+%]7+%]OOQO7+%r7+%rOOQO1G0X1G0XOAzQPO7+%rOBhQPO1G0]OOQO1G0[1G0[OOQO7+%u7+%uOVQPO<<IROBrQPO<<IQOBwQPO<<IROCOQPO'#DwOCdQPO<<ISOClQPO<<IUOCsQPO<<I^ODbQPOAN>mO*|QPOAN>lOVQPOAN>mOVQPO,5:cOOQOAN>nAN>nOVQPOAN>pOOQOG24XG24XODsQPOG24WODzQPOG24XOE]QPO1G/}OEqQPOG24[OExQPOG24[OOQOLD)rLD)rOOQOLD)sLD)sOOQOLD)vLD)vO*|QPOLD)vOFZQPO!$'MbOOQO!)9B|!)9B|",
stateData: "Fs~O!VOS~OQQORTOTROURO`UObVOcWOiXOjYOlZOnaO{dO|eO}fO!OfO!`PO!aPO!bPO!m^O!n^O!o_O!p_O!q_O!r_O~OeiO~PVOV!cXW!cXX!cXY!cXZ!cX[!cX]!cX^!cX!s!cXa!cX~Og!cXm!ZXp!ZXq!cXr!cXs!cXt!cXu!cXv!cXw!cXx!cXy!cXz!cX!T!cX~P!zOVkOWlOXmOYnOZoO[pO]qO^rOgsOqsOrsOssOtsOusOvsOwsOxsOysOzsO~O!T!WX~P$lOR{OTROURO`UObVOcWOiXOjYOlZOnaO!`PO!aPO!bPO!m^O!n^O!o_O!p_O!q_O!r_O~OQyO~P&QOR!OObVO~Od!QO~O`!RO~O`!SO~O`!TO~OV!eXW!eXX!eXY!eXZ!eX[!eX]!eX^!eXg!eXm!ZXp!ZXq!eXr!eXs!eXt!eXu!eXv!eXw!eXx!eXy!eXz!eX!T!eX!s!eXa!eX~Od!UO~Oe!VO~OR!WO~OmsOpsO~Oe!ZO~OQ!]OR![O~O!P!`O!Q!aO!R!bO!S!cO!T!WX~OQ!dO~OQRO~P&QO!s!^X~P$lO_!gOV!_XW!_XX!_XY!_XZ!_X[!_X]!_X^!_Xg!_Xq!_Xr!_Xs!_Xt!_Xu!_Xv!_Xw!_Xx!_Xy!_Xz!_X!s!_X~O_!pO!s!^X~O!s!qO~O_!rO!P!`O!Q!aO!R!bO!S!cO~Og!sO~P!zOVkOWlOXmOYnOZoO[pO]qO^rO~Oa!^X!s!^Xf!^X~P-fOa!tO!s!qO~Oe!vO~Og#OO!s!}O~Og#TO~Of#VO!s#UO~OVkOX!diY!diZ!di[!di]!di^!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~OW!di~P/ROWlO~P/ROVkOWlOXmO^rOZ!di[!di]!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~OY!di~P2xOVkOWlOXmOYnO]qO^rO[!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~OZ!di~P6hOZoO~P6hOYnO~P2xOVkOWlOXmOY!diZ!di[!di]!di^!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~O!P!Yi!Q!Yi!R!Yi!S!Yi!T!Yi_!Yia!Yik!Yih!Yi~P-fO_#YO~P-fOg#[O~Oh#]O~P-fOm#^O~Of#_O!s!qO~O_#_O~P-fOf#`O!s!qO~O!P!`O!R!vi!S!vi!T!vi_!via!vik!vih!vi~O!Q!vi~P?rO!Q!aO~P?rO!P!`O!Q!aO!R!bO!S!vi!T!vi_!via!vik!vih!vi~O_!]i!s!]ia!]if!]i~P-fOh#fO~P-fOf#gO!s!qO~OVkOWlOXmOYnOZoO[pO]qO^rO~PVOf!yi!s!yi~P-fOR#nO~Oh#oO~P-fO!P!`O!Q!aO!R!bO!S!cOa!kXk!kX~Oa#qOk#pO~Oh#rO~P-fO!P!`O!Q!aO!R!bO!S!cO!T!ty_!tya!tyk!tyh!ty~Oa#sO!P!`O!Q!aO!R!bO!S!cO~O_#yO~P-fOa#zO!P!`O!Q!aO!R!bO!S!cO~O!P!`O!Q!aO!R!bO!S!cOa!kik!ki~Oa#{O~P$lOh#|O!P!`O!Q!aO!R!bO!S!cO~Oa$OO~P-fOc!m|nTU!o!p!q!r!nQljij~",
goto: "-l!zPPPP!{PPPPPPPPPPPPPPPPPPPPPPPPPP#wPPPPPPPPPPPPPPPPPPPPPP$s$y%s&T&q'u(Q(cPPP!{*a!{+_,Z+_+_+_-Y+_PPPPPPP%s-]%s-`-c-f!s`OTUdklmnopqrs{!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|!sbOTUdklmnopqrs{!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|QjOR#e#VSgO#VQxTQ!YdQ#P!`Q#Q!aQ#R!bQ#S!cQ#i#]Q#l#bQ#m#fQ#u#oQ#v#pR#x#rmhOTd!`!a!b!c#V#]#b#f#o#p#rlcOTd!`!a!b!c#V#]#b#f#o#p#rQ!^fQ!w!RQ!y!TR#a!}!U[Uklmnopqrs{!O!S!V!W!Z![!q!s!v#O#T#[#^#n#|l]OTd!`!a!b!c#V#]#b#f#o#p#rX!]f!R!T!}UvT{![X}U!V!Z!vUwT{![Q|UQ!z!VQ!|!ZR#Z!vSSO#VQtT[zU{!V!Z![!vd!Xd!`!a!b!c#]#b#f#o#pQ!gkQ!hlQ!imQ!jnQ!koQ!lpQ!mqQ!nrQ!osQ!u!OQ!x!SQ!{!WQ#W!qQ#X!sQ#b#OQ#c#TQ#h#[Q#k#^Q#t#nQ#w#rR#}#|!n`OUdklmnopqrs!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|TuT{!s[OTUdklmnopqrs{!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|!r[OTUdklmnopqrs{!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|R!PVR#j#]R!_fRjOR!fiQ!eiR#d#U",
nodeNames: "⚠ Expression Local ( Literal Global Radical + - * \\ ∆ ∩ × ) { } Filter ComplexIndex [ ] ∈ | PrefixD PrefixI ; PrefixR := Function TextFunction :∈ ∉ ⊆ ⊄ ⊂ > ≥ < ≤ ≠ = ¬ Predicate ∀ ∃ ⇔ ⇒ &",
maxTerm: 87,
propSources: [highlighting],
skippedNodes: [0],
repeatNodeCount: 0,
tokenData: "4i~R!jX^%spq%svw&hxy&myz&rz{&w{|&||}'R}!O'W!Q!R']!R!['e![!](T!]!^(h!^!_(m!_!`(r!`!a(w!c!d(|!e!f(|!f!g)[!h!i)d!k!l)z!r!s*P!t!u*g!u!v(|!v!w(|!z!{(|!|!}*w!}#O*|#O#P+R#P#Q+W#R#S+]#T#U+]#U#V+h#V#W,z#W#X.Z#X#d+]#d#e0a#e#f+]#f#g1P#g#o+]#o#p2Q#p#q2V#q#r2[#y#z%s$f$g%s$r$s2a%o%p2f5i6S+]#BY#BZ%s$IS$I_%s$I|$JO%s$JT$JU%s$KV$KW%s% l% m2k%%Y%%Z2p%%[%%]2u%&Y%&Z2z%&]%&^3P%&_%&`3U%&`%&a3Z%&b%&c3`%&c%&d3e%'S%'T3j%'T%'U3o%'U%'V3t%(^%(_3y%(b%(c4O%(c%(d4T%)Q%)R4Y%)S%)T4_%)U%)V4d&FU&FV%s~%xY!W~X^%spq%s#y#z%s$f$g%s#BY#BZ%s$IS$I_%s$I|$JO%s$JT$JU%s$KV$KW%s&FU&FV%s~&mO!T~~&rOS~~&wO`~~&|OY~~'ROW~~'WO!u~~']OX~P'bP!^P!Q![']R'lQeQ!^P|}'r!Q!['eQ'uP!R!['xQ'}QeQ|}'r!Q!['x~(WQ!_!`(^%&b%&c(c~(cOn~~(hOq~~(mOl~~(rOx~~(wO{~~(|Ov~~)PP!Q![)S~)XPU~!Q![)S~)aPj~!Q![)S~)gQ!Q![)m#]#^)u~)rPo~!Q![)m~)zOd~~*POk~~*SQ!Q![*Y#f#g*b~*_P}~!Q![*Y~*gO!o~~*lPm~!Q![*o~*tPV~!Q![*o~*|O!d~~+ROf~~+WO[~~+]Og~~+bQ!]~#T#o+]5i6S+]~+mS!]~#T#c+]#c#d+y#d#o+]5i6S+]~,OS!]~#T#c+]#c#d,[#d#o+]5i6S+]~,aS!]~#T#`+]#`#a,m#a#o+]5i6S+]~,tQ!r~!]~#T#o+]5i6S+]~-PR!]~#T#U-Y#U#o+]5i6S+]~-_S!]~#T#f+]#f#g-k#g#o+]5i6S+]~-pS!]~#T#W+]#W#X-|#X#o+]5i6S+]~.TQ!q~!]~#T#o+]5i6S+]~.`S!]~#T#X+]#X#Y.l#Y#o+]5i6S+]~.qS!]~#T#U+]#U#V.}#V#o+]5i6S+]~/SS!]~#T#c+]#c#d/`#d#o+]5i6S+]~/eS!]~#T#c+]#c#d/q#d#o+]5i6S+]~/vS!]~#T#`+]#`#a0S#a#o+]5i6S+]~0ZQ!s~!]~#T#o+]5i6S+]~0fS!]~#T#f+]#f#g0r#g#o+]5i6S+]~0yQ!p~!]~#T#o+]5i6S+]~1US!]~#T#X+]#X#Y1b#Y#o+]5i6S+]~1gS!]~#T#W+]#W#X1s#X#o+]5i6S+]~1zQ!t~!]~#T#o+]5i6S+]~2VOa~~2[Oi~~2aOb~~2fO|~~2kO_~~2pOc~~2uO!R~~2zO!Q~~3PO!O~~3UO!P~~3ZO!c~~3`O]~~3eOh~~3jOr~~3oO!S~~3tO^~~3yOZ~~4OOz~~4TOy~~4YOw~~4_Ou~~4dOt~~4iOs~",
tokenData: "6P~R!jX^%spq%svw&hxy&myz&rz{&w{|&||}'R}!O'W!Q!R']!R!['e![!](T!]!^(h!^!_(m!_!`(r!`!a(w!c!d(|!e!f(|!f!g)[!h!i)d!k!l)z!r!s*P!t!u*g!u!v(|!v!w(|!z!{(|!|!}*w!}#O*|#O#P+R#P#Q+W#R#S+]#T#U+]#U#V+s#V#W-c#W#X/O#X#d+]#d#e1h#e#f+]#f#g2^#g#o+]#o#p3h#p#q3m#q#r3r#y#z%s$f$g%s$r$s3w%o%p3|5i6S+]#BY#BZ%s$IS$I_%s$I|$JO%s$JT$JU%s$KV$KW%s% l% m4R%%Y%%Z4W%%[%%]4]%&Y%&Z4b%&]%&^4g%&_%&`4l%&`%&a4q%&b%&c4v%&c%&d4{%'S%'T5Q%'T%'U5V%'U%'V5[%(^%(_5a%(b%(c5f%(c%(d5k%)Q%)R5p%)S%)T5u%)U%)V5z&FU&FV%s~%xY!V~X^%spq%s#y#z%s$f$g%s#BY#BZ%s$IS$I_%s$I|$JO%s$JT$JU%s$KV$KW%s&FU&FV%s~&mO!S~~&rOR~~&wO_~~&|OX~~'ROV~~'WO!s~~']OW~P'bP!`P!Q![']R'lQdQ!`P|}'r!Q!['eQ'uP!R!['xQ'}QdQ|}'r!Q!['x~(WQ!_!`(^%&b%&c(c~(cOm~~(hOp~~(mOk~~(rOw~~(wOz~~(|Ou~~)PP!Q![)S~)XPT~!Q![)S~)aPi~!Q![)S~)gQ!Q![)m#]#^)u~)rPn~!Q![)m~)zOc~~*POj~~*SQ!Q![*Y#f#g*b~*_P|~!Q![*Y~*gO!m~~*lPl~!Q![*o~*tPU~!Q![*o~*|O!b~~+ROe~~+WOZ~~+]Of~~+bRQ~!Q![+k#T#o+]5i6S+]~+pPQ~!Q![+k~+xTQ~!Q![+k#T#c+]#c#d,X#d#o+]5i6S+]~,^TQ~!Q![+k#T#c+]#c#d,m#d#o+]5i6S+]~,rTQ~!Q![+k#T#`+]#`#a-R#a#o+]5i6S+]~-YR!p~Q~!Q![+k#T#o+]5i6S+]~-hSQ~!Q![+k#T#U-t#U#o+]5i6S+]~-yTQ~!Q![+k#T#f+]#f#g.Y#g#o+]5i6S+]~._TQ~!Q![+k#T#W+]#W#X.n#X#o+]5i6S+]~.uR!o~Q~!Q![+k#T#o+]5i6S+]~/TTQ~!Q![+k#T#X+]#X#Y/d#Y#o+]5i6S+]~/iTQ~!Q![+k#T#U+]#U#V/x#V#o+]5i6S+]~/}TQ~!Q![+k#T#c+]#c#d0^#d#o+]5i6S+]~0cTQ~!Q![+k#T#c+]#c#d0r#d#o+]5i6S+]~0wTQ~!Q![+k#T#`+]#`#a1W#a#o+]5i6S+]~1_R!q~Q~!Q![+k#T#o+]5i6S+]~1mTQ~!Q![+k#T#f+]#f#g1|#g#o+]5i6S+]~2TR!n~Q~!Q![+k#T#o+]5i6S+]~2cTQ~!Q![+k#T#X+]#X#Y2r#Y#o+]5i6S+]~2wTQ~!Q![+k#T#W+]#W#X3W#X#o+]5i6S+]~3_R!r~Q~!Q![+k#T#o+]5i6S+]~3mO`~~3rOh~~3wOa~~3|O{~~4RO^~~4WOb~~4]O!Q~~4bO!P~~4gO}~~4lO!O~~4qO!a~~4vO[~~4{Og~~5QOq~~5VO!R~~5[O]~~5aOY~~5fOy~~5kOx~~5pOv~~5uOt~~5zOs~~6POr~",
tokenizers: [0, 1],
topRules: {"Expression":[0,1]},
tokenPrec: 2056
tokenPrec: 1720
})

View File

@ -17,8 +17,7 @@
log_and @left,
set_decart @left set_union @left set_intersect @left set_minus @left set_symminus @left,
set_bool @right,
quant @right,
p1, p2
quant @right
}
///////////////////////////////////////////////////////////
@ -43,7 +42,7 @@
Function { "F"$[0-9]+ }
Predicate { "P"$[0-9]+ }
Radical { "R"$[0-9]+ }
local { $[_a-zα-ω]($[a-zα-ω])* }
Local { $[_a-zα-ω]($[a-zα-ω])*$[0-9]* }
PrefixR { "R" }
PrefixI { "I" }
PrefixD { "D" }
@ -77,7 +76,7 @@
debool
red
smallPr
local
Local
}
}
@ -110,13 +109,6 @@ arguments {
declaration {
Local "∈" setexpr
}
Local {
!p1 local |
!p2 local Index
}
Index {
integer
}
variable {
Local |
tuple

View File

@ -1,74 +0,0 @@
@detectDelim
@external propSource highlighting from "./highlight"
@top Expression { token* }
@skip { space }
@tokens {
space { @whitespace+ }
Index { $[0-9]+ }
ComplexIndex { $[1-9](","$[1-9])* }
Integer { space$[0-9]+space? }
bigPr { "Pr" }
smallPr { "pr" }
filter { "Fi" }
card { "card" }
bool { "bool" }
debool { "debool" }
red { "red" }
ConstructPrefix { "D" | "R" | "I" }
Global { $[XCSDAPTF]$[0-9]+ }
Radical { "R"$[0-9]+ }
local { $[_a-zα-ω]$[a-zα-ω]* }
"(" ")"
"[" "]"
"{" "}"
@precedence {
filter
bigPr
Global
Radical
ConstructPrefix
}
@precedence {
card
bool
debool
red
smallPr
local
}
@precedence {
Integer
space
}
}
TextFunction {
bigPr ComplexIndex |
smallPr ComplexIndex |
filter ComplexIndex |
card |
bool |
debool |
red
}
Local {
local Index?
}
token {
TextFunction |
ConstructPrefix |
Integer |
Global |
Radical |
Local
}

View File

@ -4,8 +4,8 @@ import TextURL from '@/components/ui/TextURL';
import Tooltip, { PlacesType } from '@/components/ui/Tooltip';
import { useConceptOptions } from '@/context/ConceptOptionsContext';
import { HelpTopic } from '@/models/miscellaneous';
import TopicPage from '@/pages/ManualsPage/TopicPage';
import TopicPage from '../../pages/ManualsPage/TopicPage';
import { IconHelp } from '../Icons';
import { CProps } from '../props';

View File

@ -39,16 +39,16 @@ function InfoConstituenta({ data, className, ...restProps }: InfoConstituentaPro
{data.definition_resolved}
</p>
) : null}
{data.parent_alias ? (
{data.spawner_alias ? (
<p>
<b>Основание: </b>
{data.parent_alias}
{data.spawner_alias}
</p>
) : null}
{data.children_alias.length > 0 ? (
{data.spawn_alias.length > 0 ? (
<p>
<b>Порождает: </b>
{data.children_alias.join(', ')}
{data.spawn_alias.join(', ')}
</p>
) : null}
{data.convention ? (

View File

@ -3,6 +3,7 @@
*/
import { Graph } from './Graph';
import { LibraryItemID } from './library';
import { ConstituentaID, CstType, IConstituenta, IRSForm, IRSFormData, IRSFormStats } from './rsform';
import { inferClass, inferStatus, inferTemplate, isBaseSet, isFunctional } from './rsformAPI';
import { ParsingStatus, ValueClass } from './rslang';
@ -59,27 +60,39 @@ export class RSFormLoader {
}
private inferCstAttributes() {
const inherit_children = new Set(this.schema.inheritance.map(item => item[0]));
const inherit_parents = new Set(this.schema.inheritance.map(item => item[1]));
const schemaByCst = new Map<ConstituentaID, LibraryItemID>();
const parents: LibraryItemID[] = [];
this.schema.inheritance.forEach(item => {
if (item.child_source === this.schema.id) {
schemaByCst.set(item.child, item.parent_source);
if (!parents.includes(item.parent_source)) {
parents.push(item.parent_source);
}
}
});
const inherit_children = new Set(this.schema.inheritance.map(item => item.child));
const inherit_parents = new Set(this.schema.inheritance.map(item => item.parent));
this.graph.topologicalOrder().forEach(cstID => {
const cst = this.cstByID.get(cstID)!;
cst.status = inferStatus(cst.parse.status, cst.parse.valueClass);
cst.is_template = inferTemplate(cst.definition_formal);
cst.cst_class = inferClass(cst.cst_type, cst.is_template);
cst.children = [];
cst.children_alias = [];
cst.spawn = [];
cst.spawn_alias = [];
cst.parent_schema = schemaByCst.get(cst.id);
cst.parent_schema_index = cst.parent_schema ? parents.indexOf(cst.parent_schema) + 1 : 0;
cst.is_inherited = inherit_children.has(cst.id);
cst.is_inherited_parent = inherit_parents.has(cst.id);
cst.has_inherited_children = inherit_parents.has(cst.id);
cst.is_simple_expression = this.inferSimpleExpression(cst);
if (!cst.is_simple_expression || cst.cst_type === CstType.STRUCTURED) {
return;
}
cst.parent = this.inferParent(cst);
if (cst.parent) {
const parent = this.cstByID.get(cst.parent)!;
cst.parent_alias = parent.alias;
parent.children.push(cst.id);
parent.children_alias.push(cst.alias);
cst.spawner = this.inferParent(cst);
if (cst.spawner) {
const parent = this.cstByID.get(cst.spawner)!;
cst.spawner_alias = parent.alias;
parent.spawn.push(cst.id);
parent.spawn_alias.push(cst.alias);
}
});
}
@ -107,7 +120,7 @@ export class RSFormLoader {
if (sources.size !== 1 || sources.has(target.id)) {
return undefined;
}
const parent_id = sources.values().next().value as ConstituentaID;
const parent_id = sources.values().next().value!;
const parent = this.cstByID.get(parent_id);
if (parent && isBaseSet(parent.cst_type)) {
return undefined;
@ -122,7 +135,7 @@ export class RSFormLoader {
node.inputs.forEach(id => {
const parent = this.cstByID.get(id)!;
if (!parent.is_template || !parent.is_simple_expression) {
sources.add(parent.parent ?? id);
sources.add(parent.spawner ?? id);
}
});
return sources;
@ -133,7 +146,7 @@ export class RSFormLoader {
bodyDependencies.forEach(alias => {
const parent = this.cstByAlias.get(alias);
if (parent && (!parent.is_template || !parent.is_simple_expression)) {
sources.add(this.cstByID.get(parent.id)!.parent ?? parent.id);
sources.add(this.cstByID.get(parent.id)!.spawner ?? parent.id);
}
});
const needCheckHead = () => {
@ -142,7 +155,7 @@ export class RSFormLoader {
} else if (sources.size !== 1) {
return false;
} else {
const base = this.cstByID.get(sources.values().next().value as ConstituentaID)!;
const base = this.cstByID.get(sources.values().next().value!)!;
return !isFunctional(base.cst_type) || splitTemplateDefinition(base.definition_formal).head !== expression.head;
}
};
@ -151,7 +164,7 @@ export class RSFormLoader {
headDependencies.forEach(alias => {
const parent = this.cstByAlias.get(alias);
if (parent && !isBaseSet(parent.cst_type) && (!parent.is_template || !parent.is_simple_expression)) {
sources.add(parent.parent ?? parent.id);
sources.add(parent.spawner ?? parent.id);
}
});
}

View File

@ -48,7 +48,7 @@ export interface OssNodeInternal {
/**
* Represents graph node coloring scheme.
*/
export type GraphColoring = 'none' | 'status' | 'type';
export type GraphColoring = 'none' | 'status' | 'type' | 'schemas';
/**
* Represents graph node sizing scheme.

View File

@ -44,6 +44,6 @@ export function applyNodeSizing(target: IConstituenta, sizing: GraphSizing): num
} else if (sizing === 'complex') {
return target.is_simple_expression ? 1 : 2;
} else {
return target.parent ? 1 : 2;
return target.spawner ? 1 : 2;
}
}

View File

@ -101,16 +101,35 @@ export interface IConstituentaData extends IConstituentaMeta {
* Represents Constituenta.
*/
export interface IConstituenta extends IConstituentaData {
/** {@link CstClass} of this {@link IConstituenta}. */
cst_class: CstClass;
/** {@link ExpressionStatus} of this {@link IConstituenta}. */
status: ExpressionStatus;
/** Indicates if this {@link IConstituenta} is a template. */
is_template: boolean;
/** Indicates if this {@link IConstituenta} has a simple expression. */
is_simple_expression: boolean;
/** Index of {@link LibraryItemID} that contains this cst (or inheritance parent).
* 0 - not inherited, 1 - inherited by 1st schema, 2 - inherited by 2nd schema, etc.
*/
parent_schema_index: number;
/** {@link LibraryItemID} that contains parent of this inherited {@link IConstituenta}. */
parent_schema?: LibraryItemID;
/** Indicates if this {@link IConstituenta} is inherited. */
is_inherited: boolean;
is_inherited_parent: boolean;
parent?: ConstituentaID;
parent_alias?: string;
children: number[];
children_alias: string[];
/** Indicates if this {@link IConstituenta} has children that are inherited. */
has_inherited_children: boolean;
/** {@link IConstituenta} that spawned this one. */
spawner?: ConstituentaID;
/** Alias of {@link IConstituenta} that spawned this one. */
spawner_alias?: string;
/** List of {@link IConstituenta} that are spawned by this one. */
spawn: number[];
/** List of aliases of {@link IConstituenta} that are spawned by this one. */
spawn_alias: string[];
}
/**
@ -198,12 +217,22 @@ export interface IRSFormStats {
count_theorem: number;
}
/**
* Represents inheritance data for {@link IRSForm}.
*/
export interface IInheritanceData {
child: ConstituentaID;
child_source: LibraryItemID;
parent: ConstituentaID;
parent_source: LibraryItemID;
}
/**
* Represents data for {@link IRSForm} provided by backend.
*/
export interface IRSFormData extends ILibraryItemVersioned {
items: IConstituentaData[];
inheritance: ConstituentaID[][];
inheritance: IInheritanceData[];
oss: ILibraryItemReference[];
}

View File

@ -117,9 +117,9 @@ export function inferClass(type: CstType, isTemplate: boolean = false): CstClass
export function createMockConstituenta(id: ConstituentaID, alias: string, comment: string): IConstituenta {
return {
id: id,
parent: id,
children: [],
children_alias: [],
spawner: id,
spawn: [],
spawn_alias: [],
is_simple_expression: false,
schema: -1,
alias: alias,
@ -132,9 +132,10 @@ export function createMockConstituenta(id: ConstituentaID, alias: string, commen
definition_raw: '',
definition_resolved: '',
status: ExpressionStatus.INCORRECT,
parent_schema_index: 0,
is_template: false,
is_inherited: false,
is_inherited_parent: false,
has_inherited_children: false,
cst_class: CstClass.DERIVED,
parse: {
status: ParsingStatus.INCORRECT,

View File

@ -1,5 +1,3 @@
import { urls } from '@/app/urls';
import { IconLibrary2, IconManuals, IconUser2 } from '@/components/Icons';
import LinkTopic from '@/components/ui/LinkTopic';
import TextURL from '@/components/ui/TextURL';
import { HelpTopic } from '@/models/miscellaneous';
@ -22,20 +20,6 @@ function HelpMain() {
<LinkTopic text='Операционной схеме синтеза' topic={HelpTopic.CC_OSS} />.
</p>
<h2>Разделы Портала</h2>
<li>
<IconLibrary2 size='1.25rem' className='inline-icon' /> <TextURL text='Библиотека' href={urls.library} />
библиотека концептуальных схем
</li>
<li>
<IconManuals size='1.25rem' className='inline-icon' /> <TextURL text='Справка' href={urls.manuals} />
справочные материалы
</li>
<li>
<IconUser2 size='1.25rem' className='inline-icon' /> <TextURL text='Профиль' href={urls.profile} /> данные
пользователя и смена пароля
</li>
<h2>Разделы Справки</h2>
{[
HelpTopic.THESAURUS,

View File

@ -249,7 +249,7 @@ function FormConstituenta({
icon={<IconSave size='1.25rem' />}
/>
<Overlay position='top-[0.1rem] left-[0.4rem]' className='cc-icons'>
{state.is_inherited_parent && !state.is_inherited ? (
{state.has_inherited_children && !state.is_inherited ? (
<Indicator
icon={<IconPredecessor size='1.25rem' className='clr-text-primary' />}
titleHtml='Внимание!</br> Конституента имеет потомков<br/> в операционной схеме синтеза'

View File

@ -165,7 +165,11 @@ function EditorRSExpression({
toggleControls={() => setShowControls(prev => !prev)}
/>
<Overlay position='top-[-0.5rem]' className='pl-[8.5rem] xs:pl-[2rem] flex justify-center w-full gap-1'>
<Overlay
position='top-[-0.5rem]'
layer='z-pop'
className='pl-[8.5rem] xs:pl-[2rem] flex justify-center w-full gap-1'
>
<StatusBar
processing={parser.processing}
isModified={isModified}

View File

@ -15,7 +15,7 @@ function ToolbarRSExpression({ disabled, showControls, toggleControls, showAST }
const model = useRSForm();
return (
<Overlay position='top-[-0.5rem] right-0' className='cc-icons'>
<Overlay position='top-[-0.5rem] right-0' layer='z-sticky' className='cc-icons'>
{!disabled || model.processing ? (
<MiniButton
title='Отображение специальной клавиатуры'

View File

@ -261,6 +261,7 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) {
const selectors = useMemo(
() => (
<GraphSelectors
schema={controller.schema}
coloring={coloring}
layout={layout}
sizing={sizing}
@ -269,7 +270,7 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) {
setSizing={setSizing}
/>
),
[coloring, layout, sizing, handleChangeLayout, setColoring, setSizing]
[coloring, controller.schema, layout, sizing, handleChangeLayout, setColoring, setSizing]
);
const viewHidden = useMemo(
() => (

View File

@ -3,10 +3,14 @@ import { GraphLayout } from '@/components/ui/GraphUI';
import Overlay from '@/components/ui/Overlay';
import SelectSingle from '@/components/ui/SelectSingle';
import { GraphColoring, GraphSizing, HelpTopic } from '@/models/miscellaneous';
import { IRSForm } from '@/models/rsform';
import { mapLabelColoring, mapLabelLayout, mapLabelSizing } from '@/utils/labels';
import { SelectorGraphColoring, SelectorGraphLayout, SelectorGraphSizing } from '@/utils/selectors';
import SchemasGuide from './SchemasGuide';
interface GraphSelectorsProps {
schema?: IRSForm;
coloring: GraphColoring;
layout: GraphLayout;
sizing: GraphSizing;
@ -16,7 +20,7 @@ interface GraphSelectorsProps {
setSizing: (newValue: GraphSizing) => void;
}
function GraphSelectors({ coloring, setColoring, layout, setLayout, sizing, setSizing }: GraphSelectorsProps) {
function GraphSelectors({ schema, coloring, setColoring, layout, setLayout, sizing, setSizing }: GraphSelectorsProps) {
return (
<div className='border rounded-b-none select-none clr-input rounded-t-md'>
<SelectSingle
@ -30,6 +34,7 @@ function GraphSelectors({ coloring, setColoring, layout, setLayout, sizing, setS
<Overlay position='right-[2.5rem] top-[0.5rem]'>
{coloring === 'status' ? <BadgeHelp topic={HelpTopic.UI_CST_STATUS} className='min-w-[25rem]' /> : null}
{coloring === 'type' ? <BadgeHelp topic={HelpTopic.UI_CST_CLASS} className='min-w-[25rem]' /> : null}
{coloring === 'schemas' && !!schema ? <SchemasGuide schema={schema} /> : null}
</Overlay>
<SelectSingle
className='my-1'

View File

@ -0,0 +1,74 @@
import { useMemo } from 'react';
import { IconHelp } from '@/components/Icons';
import Tooltip from '@/components/ui/Tooltip';
import { useConceptOptions } from '@/context/ConceptOptionsContext';
import { useLibrary } from '@/context/LibraryContext';
import { LibraryItemID } from '@/models/library';
import { IRSForm } from '@/models/rsform';
import { colorBgSchemas } from '@/styling/color';
import { globals, prefixes } from '@/utils/constants';
interface SchemasGuideProps {
schema: IRSForm;
}
function SchemasGuide({ schema }: SchemasGuideProps) {
const { colors } = useConceptOptions();
const library = useLibrary();
const schemas = useMemo(() => {
const processed = new Set<LibraryItemID>();
const aliases: string[] = [];
const indexes: number[] = [];
schema.items.forEach(cst => {
if (cst.parent_schema && !processed.has(cst.parent_schema)) {
const item = library.items.find(item => item.id === cst.parent_schema);
if (item) {
aliases.push(item.alias);
} else {
aliases.push(`Схема ${cst.parent_schema_index}`);
}
processed.add(cst.parent_schema);
indexes.push(cst.parent_schema_index);
}
});
const result: string[] = [];
for (let i = 1; i <= aliases.length; i++) {
const trueIndex = indexes.findIndex(index => index === i);
result.push(aliases[trueIndex]);
}
return result;
}, [schema, library.items]);
return (
<div tabIndex={-1} id={globals.graph_schemas} className='p-1'>
<IconHelp size='1.25rem' className='icon-primary' />
<Tooltip
anchorSelect={`#${globals.graph_schemas}`}
layer='z-modalTooltip'
place='right'
className='max-w-[25rem] break-words text-base'
>
<div>
<span
className='min-w-[0.6rem] min-h-[0.6rem] border inline-block mr-1 rounded-full'
style={{ backgroundColor: colorBgSchemas(0, colors) }}
/>
Текущая схема
</div>
{schemas.map((alias, index) => (
<div key={`${prefixes.schemas_list}${index}`}>
<span
className='min-w-[0.6rem] min-h-[0.6rem] border inline-block mr-1 rounded-full'
style={{ backgroundColor: colorBgSchemas(index + 1, colors) }}
/>
{alias}
</div>
))}
</Tooltip>
</div>
);
}
export default SchemasGuide;

View File

@ -1,6 +1,6 @@
'use client';
import { RefObject, useCallback, useLayoutEffect, useMemo } from 'react';
import { RefObject, useCallback, useLayoutEffect } from 'react';
import GraphUI, {
CollapseProps,
@ -107,12 +107,8 @@ function TermGraph({
setSelections(newSelections);
}, [selectedIDs, setSelections, nodes]);
const canvasWidth = useMemo(() => {
return 'calc(100vw - 1rem)';
}, []);
return (
<div className='relative outline-none' style={{ width: canvasWidth, height: mainHeight }}>
<div className='relative outline-none w-[100dvw]' style={{ height: mainHeight }}>
<GraphUI
nodes={nodes}
edges={edges}

View File

@ -45,7 +45,7 @@ function useGraphFilter(schema: IRSForm | undefined, params: GraphFilterParams,
}
if (!focusCst && params.foldDerived) {
schema.items.forEach(cst => {
if (cst.parent) {
if (cst.spawner) {
graph.foldNode(cst.id);
}
});
@ -53,7 +53,7 @@ function useGraphFilter(schema: IRSForm | undefined, params: GraphFilterParams,
if (focusCst) {
const includes: ConstituentaID[] = [
focusCst.id,
...focusCst.children,
...focusCst.spawn,
...(params.focusShowInputs ? schema.graph.expandInputs([focusCst.id]) : []),
...(params.focusShowOutputs ? schema.graph.expandOutputs([focusCst.id]) : [])
];

View File

@ -109,13 +109,13 @@ function TableSideConstituents({
}
},
{
when: (cst: IConstituenta) => !!activeCst && cst.parent === activeCst?.id && cst.id !== activeCst?.id,
when: (cst: IConstituenta) => !!activeCst && cst.spawner === activeCst?.id && cst.id !== activeCst?.id,
style: {
backgroundColor: colors.bgOrange50
}
},
{
when: (cst: IConstituenta) => activeCst?.id !== undefined && cst.children.includes(activeCst.id),
when: (cst: IConstituenta) => activeCst?.id !== undefined && cst.spawn.includes(activeCst.id),
style: {
backgroundColor: colors.bgGreen50
}

View File

@ -416,6 +416,23 @@ export function colorBgCstClass(cstClass: CstClass, colors: IColorTheme): string
}
}
/**
* Determines background color for {@link IConstituenta} depending on its parent schema index.
*/
export function colorBgSchemas(schema_index: number, colors: IColorTheme): string {
if (schema_index === 0) {
return colors.bgGreen;
}
// prettier-ignore
switch (schema_index % 4) {
case 1: return colors.bgPurple;
case 2: return colors.bgOrange;
case 3: return colors.bgTeal;
case 0: return colors.bgBlue;
}
return colors.bgBlue;
}
/**
* Determines background color for {@link GramData}.
*/
@ -462,5 +479,8 @@ export function colorBgGraphNode(cst: IConstituenta, coloringScheme: GraphColori
if (coloringScheme === 'status') {
return colorBgCstStatus(cst.status, colors);
}
if (coloringScheme === 'schemas') {
return colorBgSchemas(cst.parent_schema_index, colors);
}
return '';
}

View File

@ -215,15 +215,15 @@ export function domTooltipConstituenta(cst?: IConstituenta, canClick?: boolean):
dom.appendChild(convention);
}
if (cst.parent_alias) {
if (cst.spawner_alias) {
const derived = document.createElement('p');
derived.innerHTML = `<b>Основание:</b> ${cst.parent_alias}`;
derived.innerHTML = `<b>Основание:</b> ${cst.spawner_alias}`;
dom.appendChild(derived);
}
if (cst.children_alias.length > 0) {
if (cst.spawn_alias.length > 0) {
const children = document.createElement('p');
children.innerHTML = `<b>Порождает:</b> ${cst.children_alias.join(', ')}`;
children.innerHTML = `<b>Порождает:</b> ${cst.spawn_alias.join(', ')}`;
dom.appendChild(children);
}

View File

@ -143,7 +143,8 @@ export const globals = {
email_tooltip: 'email_tooltip',
main_scroll: 'main_scroll',
library_item_editor: 'library_item_editor',
constituenta_editor: 'constituenta_editor'
constituenta_editor: 'constituenta_editor',
graph_schemas: 'graph_schemas_tooltip'
};
/**
@ -165,6 +166,7 @@ export const prefixes = {
cst_source_list: 'cst_source_list_',
cst_delete_list: 'cst_delete_list_',
cst_dependant_list: 'cst_dependant_list_',
schemas_list: 'schemas_list_',
operation_list: 'operation_list_',
csttype_list: 'csttype_',
policy_list: 'policy_list_',

View File

@ -315,7 +315,8 @@ export const mapLabelLayout = new Map<GraphLayout, string>([
export const mapLabelColoring = new Map<GraphColoring, string>([
['none', 'Цвет: Моно'],
['status', 'Цвет: Статус'],
['type', 'Цвет: Класс']
['type', 'Цвет: Класс'],
['schemas', 'Цвет: Схемы']
]);
/**