Skip to content

Full schema preview
initial_schema/person/person.esdl
# 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共有三個階級。

scalar type GangsterRank extending enum<Nobody, Leader, Boss>;

Abstract object types

Person

Person作為一個抽象的人物abstract object type,目的是希望能夠被真實世界的演員(Actor)以及劇中角色(Character)所extending。不論是演員或角色,有三個property是兩者皆具備的:

  • name property為一必填的property,為演員或劇中角色名字。
  • nickname property記錄綽號。
  • eng_name property記錄英文名字。
abstract type Person {
    required name: str;
    nickname: str;
    eng_name: str;
}

IsPolice

IsPolice有三個property

  • police_rank property代表警察官階,預設為警校學生(PoliceRank.Cadet)。
  • dept property代表警察部門。
  • is_officer property是一computed property(留意is_officer後使用的是:=,不是:),會根據police_rank是否為較高階級,來顯示truefalseenum的值是可以比較的,所以這邊可以使用>=)。
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 IsPoliceIsGangster用來表示臥底。

abstract type 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用來表示演員。

type Actor extending Person;

Police

Police同時extending CharacterIsPolice用來表示警察。

type Police extending Character, IsPolice;

Gangster

Gangster同時extending CharacterIsGangster用來表示黑社會。

type 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_rankGangsterRank.Boss

    default:= GangsterRank.Boss;
    

  • 無論是insertupdate GangsterBoss,其gangster_rank都只能指定為GangsterRank.Boss

    constraint expression on (__subject__ = GangsterRank.Boss);
    
    constraint expression on 可接受一個expression來返回truefalse,如果返回的是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 CharacterIsSpy,為警方派至黑社會之臥底。

type PoliceSpy extending Character, IsSpy;

GangsterSpy

GangsterSpy同時extending CharacterIsSpy,為黑社會派至警方之臥底。

type GangsterSpy extending Character, IsSpy;