人
Full schema preview
# scalar types
scalar type PoliceRank extending enum<Protected, Cadet, PC, SPC, SGT, SSGT, PI, IP, SIP, CIP, SP, SSP, CSP, ACP, SACP, DCP, CP>;
scalar type GangsterRank extending enum<Nobody, Leader, Boss>;
# abstract object types
abstract type Person {
required name: str;
nickname: str;
eng_name: str;
}
abstract type IsPolice {
police_rank: PoliceRank{
default:= PoliceRank.Cadet;
};
dept: str;
is_officer:= .police_rank >= PoliceRank.PI;
}
abstract type IsGangster {
gangster_rank: GangsterRank {
default:= GangsterRank.Nobody;
};
gangster_boss: GangsterBoss;
}
abstract type IsSpy extending IsPolice, IsGangster;
# object types
type Character extending Person {
classic_lines: array<str>;
lover: Character;
multi actors: Actor;
}
type Actor extending Person;
type Police extending Character, IsPolice;
type Gangster extending Character, IsGangster;
type GangsterBoss extending Gangster {
overloaded gangster_rank: GangsterRank {
default:= GangsterRank.Boss;
constraint expression on (__subject__ = GangsterRank.Boss);
};
# excluding self
constraint expression on (__subject__ != .gangster_boss) {
errmessage := "The boss can't be his/her own boss.";
}
}
type PoliceSpy extending Character, IsSpy;
type GangsterSpy extending Character, IsSpy;
Scalar types
PoliceRank
PoliceRank
共有十七個階級,其中十五個階級為依據維基百科所定義。剩餘兩個階級分別為Protected
(臥底)及Cadet
(警校學生)。
scalar type PoliceRank extending enum<Protected, Cadet, PC, SPC, SGT, SSGT, PI, IP, SIP, CIP, SP, SSP, CSP, ACP, SACP, DCP, CP>;
GangsterRank
GangsterRank
共有三個階級。
Abstract object types
Person
Person
作為一個抽象的人物abstract object type
,目的是希望能夠被真實世界的演員(Actor
)以及劇中角色(Character
)所extending
。不論是演員或角色,有三個property
是兩者皆具備的:
name
property
為一必填的property
,為演員或劇中角色名字。nickname
property
記錄綽號。eng_name
property
記錄英文名字。
IsPolice
IsPolice
有三個property
:
police_rank
property
代表警察官階,預設為警校學生(PoliceRank.Cadet
)。dept
property
代表警察部門。is_officer
property
是一computed property
(留意is_officer
後使用的是:=
,不是:
),會根據police_rank
是否為較高階級,來顯示true
或false
(enum
的值是可以比較的,所以這邊可以使用>=
)。
abstract type IsPolice {
police_rank: PoliceRank{
default:= PoliceRank.Cadet;
};
dept: str;
is_officer:= .police_rank >= PoliceRank.PI;
}
IsGangster
IsGangster
有一個property
及一個link
:
gangster_rank
property
代表黑社會階級,預設為小弟(GangsterRank.Nobody
)。gangster_boss
link
代表此角色的老大。
abstract type IsGangster {
gangster_rank: GangsterRank {
default:= GangsterRank.Nobody;
};
gangster_boss: GangsterBoss;
}
IsSpy
IsSpy
同時extending
IsPolice
及IsGangster
用來表示臥底。
Object types
Character
Character
extending
Person
用來表示劇中角色,有一個property
與兩個link
:
classic_lines
property
為一array<str>
,用來記錄角色於劇中的名言。lover
link
為劇中角色的戀人。actors
multi link
為飾演劇中角色的演員(使用multi
,因為一個角色可能由一個以上演員詮釋)。
type Character extending Person {
classic_lines: array<str>;
lover: Character;
multi actors: Actor;
}
Actor
Actor
extending
Person
用來表示演員。
Police
Police
同時extending
Character
及IsPolice
用來表示警察。
Gangster
Gangster
同時extending
Character
及IsGangster
用來表示黑社會。
GangsterBoss
GangsterBoss
extending
Gangster
而來。
type GangsterBoss extending Gangster {
overloaded gangster_rank: GangsterRank {
default:= GangsterRank.Boss;
constraint expression on (__subject__ = GangsterRank.Boss);
};
# excluding self
constraint expression on (__subject__ != .gangster_boss) {
errmessage := "The boss can't be his/her own boss.";
}
}
GangsterBoss
也算是Gangster
,只不過其gangster_rank
位階較其它黑社會成員高。為了表示這一特性,我們使用overloaded
gangster_rank
來加上兩個限制:
-
預設其
gangster_rank
為GangsterRank.Boss
: -
無論是
insert
或update
GangsterBoss
,其gangster_rank
都只能指定為GangsterRank.Boss
:constraint expression on
可接受一個expression
來返回true
或false
,如果返回的是true
的話,才能允許相關操作。而__subject__
代表此處將受限制的值(一個GangsterRank scalar
)。
此外,我們針對GangsterBoss
這個object type
也加上一個constraint
來限制自己不能是自己的gangster_boss
。其中.gangster_boss
的.
代表引用的是自身的gangster_boss
property
(定義於Gangster
中),而__subject__
則代表自己(一個GangsterBoss object
)。
constraint expression on (__subject__ != .gangster_boss) {
errmessage := "The boss can't be his/her own boss.";
}
PoliceSpy
PoliceSpy
同時extending
Character
及IsSpy
,為警方派至黑社會之臥底。
GangsterSpy
GangsterSpy
同時extending
Character
及IsSpy
,為黑社會派至警方之臥底。