diff --git a/courseC/IM_Alloy_C.html b/courseC/IM_Alloy_C.html new file mode 100644 index 0000000..3b7950f --- /dev/null +++ b/courseC/IM_Alloy_C.html @@ -0,0 +1,256 @@ + + +
+ + +
+ ここでは,InventoryManagement の Alloy による仕様記述に関する課題に取り組んでいただきます.
+ 以下に Alloy で記述された InventoryManagement のモデルを示します.こちらを適宜参照しながら課題を進めてください.
+
sig :
+ Alloy では,商品id の集合を ItemId,商品名の集合を Name,
+ 商品全体を保管する倉庫の集合を Inventory,商品の集合を Item で表します.
+ 以下のモデルでは を用いて,ItemId,Name,Inventory,Item の順番にこれらの集合を宣言しています.
+ Inventory には,ItemId から Item への対応関係が itemDB フィールドとして定義されています.
+ ここで,ItemId の右側の は1つの Item に対応する ItemId がたかだか1つしかないことを示しています.
+ Item の宣言では,商品名を表す name が Name のインスタンスとして,
+ 在庫数を表す count が Int
+
pred :
+ 最初の述語として記述されている init は,Inventory の
+ インスタンスである its が初期化されていることを示しています.
+ 次の itemRegistration は,itemId に対応する商品を登録する前の Inventory のインスタンス its と,
+ 登録した後のインスタンス its' の関係を述語として定義しています.ここで quantity は初期数量,n は商品名を示しています.
+ また,述語定義中の は,its のデータベースに登録されていない Item のインスタンス it が存在していることを示しており,
+ 直観的には Item のインスタンスの生成を示しています.
+ receivingOrShipping では itemId で登録されている商品に対して入荷か出荷を行った際の操作前の Inventory のインスタンス its と,
+ 操作後のインスタンス its' の関係を述語として定義しています.ここで quantity が正の値のときは入荷,負の値のときは出荷を表しています.
+ また,述語定義中の は,its のデータベースに登録されていない Item のインスタンス it' が存在していることを示しており,
+ 直観的には,Item のインスタンスが,出荷か入荷を行うことによって複製されたことを示しています.
+ 最後の execute では,init ,itemRegistraction ,receivingOrShipping を
+ この順で呼び出す操作を定義しています.
+ runexecute を呼び出して仮想実行を行います.
+ この実行の際に, で8bitの整数を扱うことができるよう末尾に という記述を付け加えています.
+
++sig ItemId, Name{} +sig Inventory { + itemDB: ItemIdlone ->lone Item +} +sig Item { + name : Name, + count:Int +} + +pred init[its: Inventory] { +no its.itemDB +} + +pred itemRegistration[its, its': Inventory, itemId: ItemId, quantity:Int , n: Name] { +some it: Item | { +no itemId2: ItemId | its.itemDB[itemId2] = it + its'.itemDB = its.itemDB + itemId -> it + it.name = n + it.count = quantity + } +} + +pred receivingOrShipping[its, its': Inventory, itemId: ItemId, quantity:Int ] { +some it': Item | { +no itemId2: ItemId | its.itemDB[itemId2] = it' + its'.itemDB = its.itemDB ++ itemId -> it' + it'.name = its.itemDB[itemId].name + it'.count = plus[its.itemDB[itemId].count, quantity] + } +} + +pred execute[] { +some disj its, its', its'': Inventory, itemId: ItemId, n: Name | { + init[its] + itemRegistration[its, its', itemId,100 , n] + receivingOrShipping[its', its'', itemId, -50 ] + } +} + +run executefor 2 but3 Inventory,8 Int +
+ 先ほどの InventoryManagement のモデルの構造を,Alloy の可視化ツールを使用して可視化したものを以下の図に示します.
+

+ この図がモデルの実行に依らない,モデルそのものが持つ構造を表していることに注意して下さい.
+ Inventory が,ItemId のインスタンスを Item のインスタンスに対応させる itemDB という
+ フィールドを持っており,Item が Name のインスタンスを参照する name フィールドと,
+ のインスタンスを参照する count フィールドを持っていることがわかります.
+
+ ここでは,InventoryManagement モデルの仮想実行について説明します.この仮想実行で用いるテストケースは次の通りです.
+
+ このテストケースはモデル中の execute 述語で実装されています.
+ execute の実行を可視化したものを以下に示します.
+

+ 左下にある Inventory2($execute_its) は execute 述語中の変数 its で参照される Inventory のインスタンスであり,init 述語を満たしているため,
+ まだ何の商品(Item)も登録されていない状態になっています.
+ 次に,1番上の段の左にある Inventory1($execute_its') は変数 its' で参照される Inventory のインスタンスで,
+ its で参照される Inventory のインスタンスに対して,Item のインスタンス Item1(itemRegistration_it) を初期数量100個で登録したインスタンスになっています.
+ Inventory1 の右にあるInventory0($execute_its'') は少し複雑です.
+ まず,Inventory1 において,ItemId で参照される Item のインスタンスは Item1 です.このインスタンスに対して50個出荷した後の Item のインスタンスが Item0 になります.
+ ここで Item0 の在庫数が50個に減少していることに注意して下さい.
+ ItemId で参照される Item のインスタンスが Item1 から Item0 に変わるので,Inventory のインスタンスも Inventory1 から Inventory0 に変わります.
+
+ ここからが課題です.
+ 本課題ではまず,上記にて説明を行った InventoryManagement の仕様に,ある機能を追加した仕様を考えます.
+ その仕様のモデルを以下に示します.また,そのモデルの仮想実行を可視化したものをその下に示します.これらの図を見ていただいた上で,2つの設問にお答えいただきます.
+ 設問にお答えいただく際は,必ず設問1,設問2の順番でご解答下さい.以下の図と同じものが設問のページにも記載されているのでこのまま設問のページに飛んでいただいてもかまいません.
+
++sig ItemId, Name{} +sig Inventory { + itemDB: ItemIdlone ->lone Item +} +sig Item { + name : Name, + count:Int +} + +pred init[its: Inventory] { +no its.itemDB +} + +pred itemRegistration[its, its': Inventory, itemId: ItemId, quantity:Int , n: Name] { +some it: Item | { +no itemId2: ItemId | its.itemDB[itemId2] = it + its'.itemDB = its.itemDB + itemId -> it + it.name = n + it.count = quantity + } +} + +pred shipping[its, its': Inventory, itemId: ItemId, quantity:Int ] { +some it': Item | { +no itemId2: ItemId | its.itemDB[itemId2] = it' + its'.itemDB = its.itemDB ++ itemId -> it' + it'.name = its.itemDB[itemId].name + it'.count = minus[its.itemDB[itemId].count, quantity] + } +} + +pred receiving[its, its': Inventory, itemId: ItemId, quantity:Int ] { +some it': Item | { +no itemId2: ItemId | its.itemDB[itemId2] = it' + its'.itemDB = its.itemDB ++ itemId -> it' + it'.name = its.itemDB[itemId].name + it'.count = plus[its.itemDB[itemId].count, quantity] + } +} + +pred execute[] { +some disj its, its', its'', its''': Inventory, itemId: ItemId, n: Name | { + init[its] + itemRegistration[its, its', itemId,100 , n] + shipping[its', its'', itemId,50 ] + receiving[its'', its''', itemId,25 ] + } +} + +run executefor 2 but 4 Inventory,3 Item,8 Int +

+
+
+ 課題アンケート (別タブが開きます)
+
+
+
+
+
+ 課題終了後の評価アンケート (別タブが開きます)
+
+
+
+ ここでは,InventoryManagement の DTRAM による仕様記述に関する課題に取り組んでいただきます.
+ 以下に DTRAM で記述された InventoryManagement のモデルを示します.こちらを適宜参照しながら課題を進めてください.
+
+ DTRAMでは,InventoryManagement の仕様を以下のような階層化されたリソースで表します.
+
inventory: 商品全体を保管する倉庫inventory.{itemId}: itemId で登録されている商品inventory.{itemId}.count: itemId で示された商品の在庫数inventory.{itemId}.name: itemId で示された商品の商品名ItemRegistration ,itemId で登録されている商品に対して入荷か出荷を行うためのイベントチャンネルを ReceivingOrShipping(itemId:Str ) として宣言しています.ItemRegistration チャンネルでは inventory リソースが,メッセージ registerItem(itemId, itemName, quantity) を受け取ると, リソースの状態が itemDB から insert(itemDB, itemId, {"count": quantity, "name": itemName}) に変わることを示しています.insert() 関数は,第1引数に渡された写像に対し,第2引数と第3引数の対応を追加した結果得られる写像を返す関数です.{"count": quantity, "name": itemName} は,"count" と "name" をキーに持つ JSON オブジェクトを表しています.ReceivingOrShipping(itemId:Str ) チャンネルでは inventory.{itemId}.count リソースがメッセージ receiveOrShip(quantity) を受け取ると,
+遷移前の状態 prev_quantity が prev_quantity + quantity に変わることを示しています.++channel ItemRegistration { +out inventory(itemDB:Map , registerItem(itemId:Str , itemName:Str , quantity:Int )) = insert(itemDB, itemId, {"count": quantity, "name": itemName}) +} + +channel ReceivingOrShipping(itemId:Str ) { +out inventory.{itemId}.count(prev_quantity:Int , receiveOrShip(quantity:Int )) = prev_quantity + quantity +} +
+ 先ほどの InventoryManagement のモデルのリソースとチャンネルを,DTRAM のモデリングツールを使用して可視化したものを以下の図に示します.
+

+ この図がモデルの実行に依らない,リソースとチャンネルの関係を表していることに注意して下さい.
+ 図の中央にある inventory リソースは ItemRegistration チャンネルから商品を登録するメッセージを受け取ります.
+ inventory リソースの子リソースである,inventory.{itemId} リソースは商品を表しています.
+ このリソース名に含まれる itemId は商品idを表すパスパラメータで,一意な商品の特定を可能にしています.
+ inventory.{itemId} リソースの子リソースである inventory.{itemId}.count リソースは inventory.{itemId} の在庫数を表しており,
+ ReceivingOrShipping チャンネルから入荷もしくは出荷を行うメッセージを受け取ります.
+
+ ここでは,InventoryManagement モデルの仮想実行について説明します.この仮想実行で用いるテストケースは次の通りです.
+
+ シミュレーションツールを使用すると与えられたモデルに対して,任意の仮想実行を行うことができます.
+ ここでは上で示したテストケースに従って行った仮想実行を可視化したものを示していきます.まず,システムの初期状態を可視化したものが以下の図です.
+

+ 初期状態では,inventory リソースには何の商品も登録されていない状態になっています.nil は空のマップやリストを表しています.
+ 次に,inventory に商品(Asahi)を登録するため,inventory リソースをダブルクリックします.
+

+ registerItem という商品を登録するためのメッセージを選択します.
+

+ registerItem メッセージのシグニチャが表示されます.
+ itemId は商品id,itemName は商品名 ,quantity は初期数量を表します.
+

+ ここでは,registerItem("@123", "Asahi", 100) を入力します.
+

+ 次の状態に遷移し,遷移後の状態が表示されます.@123というidを持つ商品 inventory.@123 が inventory の子リソースとして生成されていることがわかります.
+ inventory.@123 の在庫数量 inventory.@123.count が100,商品名 inventory.@123.name がAsahiとなっていることを確認できます.
+ 次に,登録した商品 inventory.@123 を50個出荷したいので,inventory.@123.count リソースをダブルクリックします.
+

+ メッセージを選択する画面が同様に表示されますので,入荷か出荷を行う receiveOrShip というメッセージを選択します.
+

+ 入荷数量,または出荷数量の入力が可能な画面が表示されますので,ここでは receiveOrShip(-50) と入力して実行します.
+ ここで quantity が正の値のときは入荷,負の値のときは出荷が行われます.
+

+ 次の状態に遷移したため,inventory.@123.count リソースの状態が50に遷移したことが確認できました.
+
+ ここからが課題です.
+ 本課題ではまず,上記にて説明を行った InventoryManagement の仕様に,ある機能を追加した仕様を考えます.
+ その仕様のモデルを以下に示します.また,そのモデルの仮想実行を可視化したものをその下に示します.これらの図を見ていただいた上で,2つの設問にお答えいただきます.
+ 設問にお答えいただく際は,必ず設問1,設問2の順番でご解答下さい.以下の図と同じものが設問のページにも記載されているのでこのまま設問のページに飛んでいただいてもかまいません.
+
++channel ItemRegistration { +out inventory(itemDB:Map , registerItem(itemId:Str , itemName:Str , quantity:Int )) = insert(itemDB, itemId, {"count": quantity, "name": itemName}) +} + +channel ReceivingOrShipping(itemId:Str ) { +out inventory.{itemId}.count(prev_quantity:Int , receiveOrShip(quantity:Int )) = if(prev_quantity + quantity >= 0, prev_quantity + quantity, prev_quantity) +} +







+
+
+ 課題アンケート (別タブが開きます)
+
+
+
+
+
+ 課題終了後の評価アンケート (別タブが開きます)
+
+
+
+ ここでは,SimpleTwitter の Alloy による仕様記述に関する課題に取り組んでいただきます.
+ 以下に Alloy で記述された SimpleTwitter のモデルを示します.こちらを適宜参照しながら課題を進めてください.
+
sig :
+ Alloy では,アカウントidの集合を AccountId,アカウント名の集合を Name,
+ ツイートの集合を Tweet,アカウントデータベースの集合を Accounts,アカウントの集合を Account,ツイートリストの集合を List で表します.
+ 以下のモデルでは を用いて,AccountId,Name,Tweet,Accounts,Account,List の順番にこれらの集合を宣言しています.
+ Accounts には,AccountId から Account への対応関係が accountDB フィールドとして定義されています.
+ ここで,AccountId の右側の は1つの Account に対応する AccountId がたかだか1つしかないことを示しています.
+ Account の宣言では,アカウント名を表す name が Name のインスタンスとして,
+ ツイートリストを表す tweets が List のインスタンスとして定義されています.
+
+
pred :
+ 最初の述語として記述されている init は,Accounts の
+ インスタンスである acs が初期化されていることを示しています.
+ 次の signUp は,id に対応するアカウントを登録する前の Accounts のインスタンス acs と,
+ 登録した後のインスタンス acs' の関係を述語として定義しています.ここで n はアカウント名を示しています.
+ また,述語定義中の は,acs のデータベースに登録されていない Account のインスタンス ac が存在していることを示しており,
+ 直観的には Account のインスタンスの生成を示しています.
+ tweet ではid で登録されているアカウントに対してツイートを行った際の操作前の Accounts のインスタンス acs と,
+ 操作後のインスタンス acs' の関係を述語として定義しています.ここで contents はツイートの内容を表しています.
+ 述語定義中の は,acs のデータベースに登録されていない Account のインスタンス ac' が存在していることを示しており,
+ 直観的には,Account のインスタンスが,ツイートを行うことによって複製されたことを示しています.
+ また は,その前に記述されている条件が成り立っているときは,その後に記述されている論理式または論理式の集合が成り立ち,条件が成り立っていないときは の後ろに記述されている論理式または論理式の集合が成り立つことを示しています.
+ 最後の execute では,init,signUp,tweet をこの順で呼び出す操作を定義しています.
+ runexecute を呼び出して仮想実行を行います.
+
++sig AccountId, Name, Tweet { } +sig Accounts { + accountDB: AccountIdlone ->lone Account +} +sig Account { + name: Name, + tweets: List +} + +sig List { + size:Int , + element:Int ->lone Tweet +} + +pred init[acs: Accounts] { +no acs.accountDB +} + +pred signUp[acs, acs': Accounts, id: AccountId, n: Name] { +some ac: Account | { +no id2: AccountId | acs.accountDB[id2] = ac + acs'.accountDB = acs.accountDB + id -> ac + ac.name = n + ac.tweets.size =0 +no ac.tweets.element + } +} + +pred tweet[acs, acs': Accounts, id: AccountId, contents: Tweet] { +some ac': Account | { +no id2: AccountId | acs.accountDB[id2] = ac' + acs'.accountDB = acs.accountDB ++ id -> ac' + ac'.name = acs.accountDB[id].name + ac'.tweets != acs.accountDB[id].tweets + ac'.tweets.size = plus[acs.accountDB[id].tweets.size,1 ] + ac'.tweets.element[minus[ac'.tweets.size,1 ]] = contents +all n:Int | n != minus[ac'.tweets.size,1 ]implies ac'.tweets.element[n] = acs.accountDB[id].tweets.element[n] + } +} + +pred execute[] { +some disj acs, acs', acs'': Accounts, id: AccountId, n: Name, contents: Tweet | { + init[acs] + signUp[acs, acs', id, n] + tweet[acs', acs'', id, contents] + } +} + +run executefor 2 but 3 Accounts +
+ 先ほどの SimpleTwitter のモデルの構造を,Alloy の可視化ツールを使用して可視化したものを以下の図に示します.
+

+ この図がモデルの実行に依らない,モデルそのものが持つ構造を表していることに注意して下さい.
+ Accounts が,AccountId のインスタンスを Account のインスタンスに対応させる accountDB というフィールドを持っており,
+ Account が Name のインスタンスを参照する name フィールドと,List のインスタンスを参照する tweets フィールドを,
+ List が のインスタンスを参照する size フィールドと,
+ のインスタンスを Tweet のインスタンスに対応させる element フィールドをもっていることがわかります.
+
+ ここでは,SimpleTwitter モデルの仮想実行について説明します.この仮想実行で用いるテストケースは次の通りです.
+
+ このテストケースはモデル中の execute 述語で実装されています.
+ execute の仮想実行を可視化したものを以下に示します.
+

+ 左下にある Accounts2($execute_acs) は execute 述語中の変数 acs で参照される Accounts のインスタンスであり,init 述語を満たしているため,
+ まだ何のアカウント(Account)も登録されていない状態になっています.
+ 次に,1番上の段の左にある Accounts1($execute_acs') は変数 acs' で参照される Account のインスタンスで,
+ acs で参照される Account のインスタンスに対して,Account のインスタンス Account1($signUp_ac) をツイートリストの要素数が0の状態で登録したインスタンスになっています.
+ Accounts1 の右にある Accounts0($execute_acs'') は少し複雑です.
+ まず,Accounts1 において,AccountId で参照される Account のインスタンスは Account1 です.このインスタンスに対してツイートを行った後の Account のインスタンスは Account0 になります.
+ ここで Account0 のツイートリストの要素数が1に増加していることに注意して下さい.
+ AccountId で参照される Account のインスタンスが Account1 から Account0 に変わるので,Accounts のインスタンスも Accounts1 から Accounts0 に変わります.
+
+ ここからが課題です.
+ 本課題ではまず,上記にて説明を行った SimpleTwitter の仕様に,ある機能を追加した仕様を考えます.
+ その仕様のモデルを以下に示します.また,そのモデルの仮想実行を可視化したものをその下に示します.これらの図を見ていただいた上で,2つの設問にお答えいただきます.
+ 設問にお答えいただく際は,必ず設問1,設問2の順番でご解答下さい.以下の図と同じものが設問のページにも記載されているのでこのまま設問のページに飛んでいただいてもかまいません.
+
++sig AccountId, Name, Tweet { } +sig Accounts { + accountDB: AccountIdlone ->lone Account +} +sig Account { + name: Name, + tweets: List +} + +sig List { + size:Int , + element:Int ->lone Tweet +} + +pred init[acs: Accounts] { +no acs.accountDB +} + +pred signUp[acs, acs': Accounts, id: AccountId, n: Name] { +some ac: Account | { +no id2: AccountId | acs.accountDB[id2] = ac + acs'.accountDB = acs.accountDB + id -> ac + ac.name = n + ac.tweets.size =0 +no ac.tweets.element + } +} + +pred tweet[acs, acs': Accounts, id: AccountId, contents: Tweet] { +some ac': Account | { +no id2: AccountId | acs.accountDB[id2] = ac' + acs'.accountDB = acs.accountDB ++ id -> ac' + ac'.name = acs.accountDB[id].name + ac'.tweets != acs.accountDB[id].tweets + ac'.tweets.size = plus[acs.accountDB[id].tweets.size,1 ] + ac'.tweets.element[minus[ac'.tweets.size,1 ]] = contents +all n:Int | n != minus[ac'.tweets.size,1 ]implies ac'.tweets.element[n] = acs.accountDB[id].tweets.element[n] + } +} + +pred changeName[acs, acs': Accounts, id: AccountId, n: Name] { +some ac': Account | { +no id2: AccountId | acs.accountDB[id2] = ac' + acs'.accountDB = acs.accountDB ++ id -> ac' + ac'.name = n + ac'.tweets = acs.accountDB[id].tweets + } +} + +pred execute[] { +some disj acs, acs', acs'', acs''': Accounts, id: AccountId,disj n, n': Name, contents: Tweet | { + init[acs] + signUp[acs, acs', id, n] + tweet[acs', acs'', id, contents] + changeName[acs'', acs''', id, n'] + } +} + +run executefor 2 but 4 Accounts,3 Account + +

+
+
+ 課題アンケート (別タブが開きます)
+
+
+
+
+
+ 課題終了後の評価アンケート (別タブが開きます)
+
+
+
+ ここでは,SimpleTwitter の DTRAM による仕様記述に関する課題に取り組んでいただきます.
+ 以下に DTRAM で記述された SimpleTwitter のモデルを示します.こちらを適宜参照しながら課題を進めてください.
+
+ DTRAM では,SimpleTwitter の仕様を以下のような階層化されたリソースで表します.
+
accounts: アカウント全体を管理するデータベースaccounts.{accountId}: accountId で登録されているアカウントaccounts.{accountId}.name: accountId で示されたアカウントのアカウント名accounts.{accountId}.tweets: accountId で示されたアカウントのツイートリストaccounts.{accountId}.tweets.{tid}: accountId で示されたアカウントのツイートリストの tid 番目のツイートSignup ,accountId で登録されているアカウントに対してツイートを行うためのイベントチャンネルを Tweet(accountId:Str ) として宣言しています.Signup チャンネルでは accounts リソースが,メッセージ signUp(accountId, name) を受け取ると, リソースの状態が accountDB から insert(accountDB, accountId, {"name": name, "tweets": nil}) に変わることを示しています.nil は空のマップやリストを表しています.insert() 関数は,第1引数に渡された写像に対し,第2引数と第3引数の対応を追加した結果得られる写像を返す関数です.また {"name": name, "tweets": nil} は,"name" と "tweets" をキーに持つ JSON オブジェクトを表しています.Tweet(accountId:Str ) チャンネルでは accounts.{accountId}.tweets リソースがメッセージ tweet(contents) を受け取ると,
+遷移前の状態 tweetList が append(tweetList, contents) に変わることを示しています.append() 関数は,第1引数に渡されたリストに対し,第2引数のオブジェクトを末尾に追加した結果得られるリストを返す関数です.++channel Signup { +out accounts(accountDB:Map , signUp(accountId:Str , name:Str )) = insert(accountDB, accountId, {"name": name, "tweets": nil}) +} + +channel Tweet(accountId:Str ) { +out accounts.{accountId}.tweets(tweetList:List , tweet(contents:Str )) = append(tweetList, contents) +} +
+ 先ほどの SimpleTwitter のモデルのリソースとチャンネルを,DTRAM のモデリングツールを使用して可視化したものを以下の図に示します.
+

+ この図がモデルの実行に依らない,リソースとチャンネルの関係を表していることに注意して下さい.
+ 図の中央にある accounts リソースは Signup チャンネルからアカウントを登録するメッセージを受け取ります.
+ accounts リソースの子リソースである,accounts.{accountId} リソースはアカウントを表しています.
+ このリソース名に含まれる accountId はアカウントidを表すパスパラメータで,一意なアカウントの特定を可能にしています.
+ accounts.{accountId} リソースの子リソースである accounts.{accountId}.tweets リソースは accounts.{accountId} のツイートリストを表しており,
+ Tweet チャンネルからツイートを行うメッセージを受け取ります.
+
+ ここでは,SimpleTwitter モデルの仮想実行について説明します.この仮想実行で用いるテストケースは次の通りです.
+
+ シミュレーションツールを使用すると与えられたモデルに対して,任意の仮想実行を行うことができます.
+ ここでは上で示したテストケースに従って行った仮想実行を可視化したものを示していきます.まず,システムの初期状態を可視化したものが以下の図です.
+

+ 初期状態では,accounts リソースには何のアカウントも登録されていない状態になっています.
+ 次に,accounts にアカウント名が "Satou" のアカウントを登録するため,accounts リソースをダブルクリックします.
+

+ signUp というアカウントを登録するためのメッセージを選択します.
+

+ signUp メッセージのシグニチャが表示されます.
+ accountId はアカウントid,name はアカウント名を表します.
+

+ ここでは,signUp("@123", "Satou") を入力します.
+

+ 次の状態に遷移し,遷移後の状態が表示されます.@123というidを持つアカウント accounts.@123 が accounts の子リソースとして生成されていることがわかります.
+ accounts.@123 のツイートリスト accounts.@123.tweets が 空のリスト(nil),アカウント名 accounts.@123.name が "Satou" となっていることを確認できます.
+ 次に,登録したアカウント accounts.@123 でツイートを行いたいので,accounts.@123.tweets リソースをダブルクリックします.
+

+ メッセージを選択する画面が同様に表示されますので,ツイートを行う tweet というメッセージを選択します.
+

+ ツイート内容の入力が可能な画面が表示されますので,ここでは tweet("Hello") と入力して実行します.
+

+ 次の状態に遷移したため,Hello というツイート内容を持つツイート accounts.@123.tweets.0 が accounts.@123.tweets の子リソースとしてツイートリストの0番目に生成されていることが確認できました.
+
+ ここからが課題です.
+ 本課題ではまず,上記にて説明を行った SimpleTwitter の仕様に,ある機能を追加した仕様を考えます.
+ その仕様のモデルを以下に示します.また,そのモデルの仮想実行を可視化したものをその下に示します.これらの図を見ていただいた上で,2つの設問にお答えいただきます.
+ 設問にお答えいただく際は,必ず設問1,設問2の順番でご解答下さい.以下の図と同じものが設問のページにも記載されているのでこのまま設問のページに飛んでいただいてもかまいません.
+
++channel Signup { +out accounts(accountDB:Map , signUp(accountId:Str , name:Str )) = if(contains(accountDB, accountId), accountDB, insert(accountDB, accountId, {"name": name, "tweets": nil})) +} + +channel Tweet(accountId:Str ) { +out accounts.{accountId}.tweets(tweetList:List , tweet(contents:Str )) = append(tweetList, contents) +} + +





+
+
+ 課題アンケート (別タブが開きます)
+
+
+
+
+
+ 課題終了後の評価アンケート (別タブが開きます)
+
+
+