School Commit Init

This commit is contained in:
2024-08-31 12:07:21 +03:00
commit 0b130ee18c
2801 changed files with 4720552 additions and 0 deletions
@@ -0,0 +1,145 @@
USE "Gwent - The Witcher Card Game"
CREATE TABLE Factions(
hmy INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
name VARCHAR(255) NOT NULL,
totalMatches INT NOT NULL DEFAULT 0,
totalWins INT NOT NULL DEFAULT 0,
totalLosses INT NOT NULL DEFAULT 0,
totalDraws INT NOT NULL DEFAULT 0,
totalCards INT NOT NULL DEFAULT 0,
)
CREATE TABLE CardSet(
hmy INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
name VARCHAR(255) NOT NULL,
image VARCHAR(255) NOT NULL,
releaseDate DATE NOT NULL,
)
CREATE TABLE Cards(
hmy INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
name VARCHAR(255) NOT NULL,
faction INT NOT NULL references Factions(hmy),
description VARCHAR(1000) NOT NULL,
action VARCHAR(1000) NOT NULL,
image VARCHAR(255) NOT NULL,
cost INT NOT NULL,
type VARCHAR(255) NOT NULL,
power INT,
color VARCHAR(255) NOT NULL,
cardset INT NOT NULL references CardSet(hmy),
CHECK(type in ('unit', 'special', 'artifact', 'stratagem')),
CHECK(color in ('bronze', 'gold')),
)
CREATE TABLE Players(
hmy INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
name VARCHAR(255) NOT NULL,
totalMatches INT NOT NULL DEFAULT 0,
totalWins INT NOT NULL DEFAULT 0,
totalLosses INT NOT NULL DEFAULT 0,
totalDraws INT NOT NULL DEFAULT 0,
reward_points INT NOT NULL DEFAULT 0,
scraps INT NOT NULL DEFAULT 0,
ores INT NOT NULL DEFAULT 0,
meteorite_powder INT NOT NULL DEFAULT 0,
rank INT NOT NULL DEFAULT 30,
)
CREATE TABLE CardsOwnership(
hCard INT NOT NULL references Cards(hmy),
hPlayer INT NOT NULL references Players(hmy),
nrOfCards INT NOT NULL,
nrOfPremiumCards INT NOT NULL,
CHECK(nrOfCards in (0,1,2)),
CHECK(nrOfPremiumCards in (0,1,2)),
CHECK(nrOfCards + nrOfPremiumCards <= 2 AND nrOfCards + nrOfPremiumCards >= 0),
PRIMARY KEY(hCard, hPlayer)
)
CREATE TABLE Matches(
hmy INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
hPlayer1 INT NOT NULL references Players(hmy),
hPlayer1Faction INT NOT NULL references Factions(hmy),
hPlayer2 INT NOT NULL references Players(hmy),
hPlayer2Faction INT NOT NULL references Factions(hmy),
result INT NOT NULL,
CHECK(result in (1,2,3)),
CHECK(hPlayer1 != hPlayer2)
)
CREATE TABLE Cosmetics(
hmy INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
name VARCHAR(255) NOT NULL,
image VARCHAR(255) NOT NULL,
type VARCHAR(255) NOT NULL,
description VARCHAR(255) NOT NULL,
CHECK(type in ('avatar', 'title', 'border', 'leader', 'cardback', 'coin'))
)
CREATE TABLE CosmeticsOwnership(
hCosmetic INT NOT NULL references Cosmetics(hmy),
hPlayer INT NOT NULL references Players(hmy),
PRIMARY KEY(hCosmetic, hPlayer)
)
CREATE TABLE Journeys(
hmy INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
storyPanel1 VARCHAR(8000) NOT NULL,
storyPanel2 VARCHAR(8000) NOT NULL,
storyPanel3 VARCHAR(8000) NOT NULL,
storyPanel4 VARCHAR(8000) NOT NULL,
storyPanel5 VARCHAR(8000) NOT NULL,
storyPanel6 VARCHAR(8000) NOT NULL,
storyPanel7 VARCHAR(8000) NOT NULL,
storyPanel8 VARCHAR(8000) NOT NULL,
storyPanel9 VARCHAR(8000) NOT NULL,
storyPanel10 VARCHAR(8000) NOT NULL,
storyPanel11 VARCHAR(8000) NOT NULL,
storyPanel12 VARCHAR(8000) NOT NULL,
level6Reward INT NOT NULL references Cosmetics(hmy),
level12Reward INT NOT NULL references Cosmetics(hmy),
level18Reward INT NOT NULL references Cosmetics(hmy),
level24Reward INT NOT NULL references Cosmetics(hmy),
level30Reward INT NOT NULL references Cosmetics(hmy),
level36Reward INT NOT NULL references Cosmetics(hmy),
level42Reward INT NOT NULL references Cosmetics(hmy),
level48Reward INT NOT NULL references Cosmetics(hmy),
level54Reward INT NOT NULL references Cosmetics(hmy),
level60Reward INT NOT NULL references Cosmetics(hmy),
level66Reward INT NOT NULL references Cosmetics(hmy),
level72Reward INT NOT NULL references Cosmetics(hmy),
level78Reward INT NOT NULL references Cosmetics(hmy),
level84Reward INT NOT NULL references Cosmetics(hmy),
level90Reward INT NOT NULL references Cosmetics(hmy),
level96Reward INT NOT NULL references Cosmetics(hmy),
level100Reward INT NOT NULL references Cosmetics(hmy),
)
CREATE TABLE JourneyProgress(
hJourney INT NOT NULL references Journeys(hmy),
hPlayer INT NOT NULL references Players(hmy),
level INT NOT NULL DEFAULT 1,
PRIMARY KEY(hJourney, hPlayer)
)
CREATE TABLE Decks(
hmy INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
name VARCHAR(255) NOT NULL,
faction INT NOT NULL references Factions(hmy),
strategem INT NOT NULL references Cards(hmy),
nrOfCards INT NOT NULL,
nrOfNeutralCards INT NOT NULL,
owner INT NOT NULL references Players(hmy),
)
CREATE TABLE DecksCards(
hDeck INT NOT NULL references Decks(hmy),
hCard INT NOT NULL references Cards(hmy),
nrOfCards INT NOT NULL,
CHECK(nrOfCards in (1,2)),
PRIMARY KEY(hDeck, hCard)
)
+144
View File
@@ -0,0 +1,144 @@
--- 1.
CREATE DATABASE Airbnb
CREATE TABLE Customers(
id int primary key,
username VARCHAR(100),
nationality VARCHAR(100),
dateofbirth DATE,
)
ALTER TABLE Customers
ADD UNIQUE (username);
CREATE TABLE Emails(
id int primary key,
email VARCHAR(256),
userid int FOREIGN key REFERENCES Customers(id)
)
CREATE TABLE Properties(
id int primary key,
name varchar(100),
decription varchar(100),
checkin Time,
checkout Time,
numberofpeople int,
price decimal(18,2),
freecancellation bit
)
CREATE TABLE Bookings(
id int primary key,
client int FOREIGN key REFERENCES Customers(id),
property int FOREIGN key REFERENCES Properties(id),
startdate DATE,
enddate DATE,
)
CREATE TABLE Payments(
id int primary key,
amount decimal(18,2),
dateofpayment DATETIME,
typeofpayment VARCHAR(100),
booking int FOREIGN key REFERENCES Bookings(id)
)
--- 2.
GO
CREATE OR ALTER PROCEDURE addPayment @amount int, @typeofpay VARCHAR(100), @booking int
AS
BEGIN
IF NOT EXISTS(SELECT 1 FROM Bookings where id=@booking)
begin
RAISERROR('Invalid Booking',17,1);
end
DECLARE @TOTAL DECIMAL(18,2);
SET @TOTAL=(SELECT SUM(amount) FROM Payments p WHERE p.booking= @booking);
DECLARE @Totaltopay DECIMAL(18,2)
SET @Totaltopay= (SELECT price*DATEDIFF(DAY,b.startdate,b.enddate) FROM Properties p join Bookings b on p.id=b.property WHERE b.id=@booking)
IF @TOTAL < @Totaltopay
BEGIN
INSERT INTO Payments (id, amount, dateofpayment, typeofpayment, booking)
VALUES
(
(SELECT MAX(id)+1 FROM Payments),
@amount,
GETDATE(),
@typeofpay,
@booking
)
END
END
--- 3.
GO
CREATE VIEW maxBookers
AS
SELECT username FROM Customers c join Bookings b on c.id=b.client
GROUP BY username
HAVING COUNT(b.id) = (SELECT TOP 1 COUNT(b.id) FROM Customers c join Bookings b on c.id=b.client
GROUP BY username ORDER BY COUNT(b.id) DESC)
GO
--- 4.
CREATE OR ALTER FUNCTION lessThanR (@r int)
RETURNS int AS
BEGIN
DECLARE @res int;
SET @res = (SELECT COUNT(*) FROM Customers c Join Bookings b on c.id=b.client JOIN Payments p ON p.booking=b.id
WHERE EXISTS(SELECT * FROM Bookings b2 INNER JOIN Payments p2 on p2.booking=b2.id WHERE p2.typeofpayment='PayPal' and b2.id=b.id)
GROUP BY c.username HAVING COUNT(b.id)<@r);
IF ISNULL(@res, 0)=0
BEGIN
return 0
END
RETURN @res
END
GO
--- inserts
INSERT INTO Customers (id,
username ,
nationality ,
dateofbirth)
VALUES
(1,'Andrei','Romania', '2001-01-01'),
(2,'Mircea','Grecia', '2002-02-02'),
(3,'Vlad','Danemarca', '2003-03-03')
INSERT INTO Emails (id, email, userid)
VALUES
(1,'andrei@yahoo.com',1),
(2,'andrei2@yahoo.com',1),
(3,'mircea@yahoo.com',2),
(4,'vlad@yahoo.com',3)
INSERT INTO Properties (
id,
name ,
decription ,
checkin,
checkout,
numberofpeople,
price,
freecancellation
)
VALUES
(1,'Pensiune','Descrierre','10:30:00', '09:00:00', 10, 400.50, 1),
(2,'Hotel','Descrierre','10:30:00', '09:00:00', 5, 1000.50, 0)
INSERT INTO Bookings (id, client, property, startdate, enddate)
VALUES
(1,1,1,'2023-11-11','2023-11-12'),
(2,3,2,'2023-10-10','2023-10-12')
DECLARE @ret int
EXEC @ret = lessThanR @r=100
SELECT @ret
@@ -0,0 +1,86 @@
USE "Gwent - The Witcher Card Game"
DECLARE @i INT = 0;
DECLARE @count INT = 0;
SELECT @count = Count(*) FROM Cards
WHILE @i <= @count
BEGIN
INSERT INTO CardsOwnership (hPlayer, hCard, nrOfCards, nrOfPremiumCards)
VALUES (
(SELECT hmy FROM Players WHERE name = 'Sif_Great_Wolf'),
(SELECT hmy FROM Cards
ORDER BY hmy
OFFSET @i ROWS
FETCH NEXT 1 ROWS ONLY ),
0,2
)
INSERT INTO CardsOwnership (hPlayer, hCard, nrOfCards, nrOfPremiumCards)
VALUES (
(SELECT hmy FROM Players WHERE name = 'Nik-r'),
(SELECT hmy FROM Cards
ORDER BY hmy
OFFSET @i ROWS
FETCH NEXT 1 ROWS ONLY ),
0,2
)
SET @i = @i + 1;
END
SET @i = 0;
SELECT @count = Count(*) FROM Cards
WHILE @i <= @count
BEGIN
INSERT INTO CardsOwnership (hPlayer, hCard, nrOfCards, nrOfPremiumCards)
VALUES (
(SELECT hmy FROM Players WHERE name = 'Daniel.Cujba.54'),
(SELECT hmy FROM Cards
ORDER BY hmy
OFFSET @i ROWS
FETCH NEXT 1 ROWS ONLY ),
0,2
)
INSERT INTO CardsOwnership (hPlayer, hCard, nrOfCards, nrOfPremiumCards)
VALUES (
(SELECT hmy FROM Players WHERE name = 'RaChid-bhk'),
(SELECT hmy FROM Cards
ORDER BY hmy
OFFSET @i ROWS
FETCH NEXT 1 ROWS ONLY ),
0,2
)
SET @i = @i + 30;
END
SET @i = 0;
SELECT @count = Count(*) FROM Cards
WHILE @i <= @count
BEGIN
INSERT INTO CardsOwnership (hPlayer, hCard, nrOfCards, nrOfPremiumCards)
VALUES (
(SELECT hmy FROM Players WHERE name = 'lerio2'),
(SELECT hmy FROM Cards
ORDER BY hmy
OFFSET @i ROWS
FETCH NEXT 1 ROWS ONLY ),
0,2
)
INSERT INTO CardsOwnership (hPlayer, hCard, nrOfCards, nrOfPremiumCards)
VALUES (
(SELECT hmy FROM Players WHERE name = 'Mya-Mon369EX'),
(SELECT hmy FROM Cards
ORDER BY hmy
OFFSET @i ROWS
FETCH NEXT 1 ROWS ONLY ),
0,2
)
SET @i = @i + 10;
END
@@ -0,0 +1,15 @@
USE "Gwent - The Witcher Card Game"
INSERT INTO CardSet(name, image, releaseDate)
VALUES('Starter Set', 'https://gwent.one/img/icon/search/set/starter.png', '2018-10-23'),
('Base Set','https://gwent.one/img/icon/search/set/base.png','2018-10-23'),
('Thronebreaker','https://gwent.one/img/icon/search/set/thronebreaker.png','2018-10-23'),
('Crimson Curse', 'https://gwent.one/img/icon/search/set/crimson-curse.png', '2019-03-28'),
('Novigrad', 'https://gwent.one/img/icon/search/set/novigrad.png', '2019-06-28'),
('Iron Judgment', 'https://gwent.one/img/icon/search/set/iron-judgment.png', '2019-10-02'),
('Merchants of Ofir', 'https://gwent.one/img/icon/search/set/merchants-of-ofir.png', '2019-12-09'),
('Master Mirror', 'https://gwent.one/img/icon/search/set/master-mirror.png', '2020-06-30'),
('Way of the Witcher', 'https://gwent.one/img/icon/search/set/way-of-the-witcher.png', '2020-12-08'),
('Price of Power', 'https://gwent.one/img/icon/search/set/price-of-power.png', '2021-06-08'),
('Cursed Toad', 'https://gwent.one/img/icon/search/set/cursed_toad.png', '2022-04-04'),
('Uroboros', 'https://gwent.one/img/icon/search/set/uroboros.png', '2023-04-13')
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,153 @@
USE "Gwent - The Witcher Card Game"
DECLARE @i INT = 0;
DECLARE @count INT = 0;
SELECT @count = Count(*) FROM Cosmetics
WHILE @i <= @count
BEGIN
INSERT INTO CosmeticsOwnership (hPlayer, hCosmetic)
VALUES (
(SELECT hmy FROM Players WHERE name = 'Sif_Great_Wolf'),
(SELECT hmy FROM Cosmetics
ORDER BY hmy
OFFSET @i ROWS
FETCH NEXT 1 ROWS ONLY )
)
INSERT INTO CosmeticsOwnership (hPlayer, hCosmetic)
VALUES (
(SELECT hmy FROM Players WHERE name = 'Nik-r'),
(SELECT hmy FROM Cosmetics
ORDER BY hmy
OFFSET @i ROWS
FETCH NEXT 1 ROWS ONLY )
)
SET @i = @i + 1;
END
DECLARE @player INT = (SELECT hmy FROM Players WHERE name = 'Daniel.Cujba.54')
INSERT INTO CosmeticsOwnership (hPlayer, hCosmetic)
VALUES (
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Slave Handler')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Duke of Dogs Skin')
)
SET @player = (SELECT hmy FROM Players WHERE name = 'RaChid-bhk')
INSERT INTO CosmeticsOwnership (hPlayer, hCosmetic)
VALUES(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Happy Ciri')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Ciri Nova')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Wild Hunt Pursuit Cardback')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Kitsune')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Skellige Ciri')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Hooded Ciri')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Fire Possession Cardback')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Ciri Kaer Morhen Adept')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Sack Mascote Ciri')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Downsize Ciri')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Purple Portal Animated Border')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Sword Coin')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Cirilla Fiona Elen Riannon')
)
SET @player = (SELECT hmy FROM Players WHERE name = 'lerio2')
INSERT INTO CosmeticsOwnership (hPlayer, hCosmetic)
VALUES(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Happy Ciri')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Ciri Nova')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Wild Hunt Pursuit Cardback')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Kitsune')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Skellige Ciri')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Hooded Ciri')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Fire Possession Cardback')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Ciri Kaer Morhen Adept')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Sack Mascote Ciri')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Downsize Ciri')
)
SET @player = (SELECT hmy FROM Players WHERE name = 'Mya-Mon369EX')
INSERT INTO CosmeticsOwnership (hPlayer, hCosmetic)
VALUES(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'OF LYRIA')
),
(
@player,
(SELECT hmy FROM Cosmetics WHERE name = 'Duke of Dogs Skin')
)
@@ -0,0 +1,29 @@
USE "Gwent - The Witcher Card Game"
INSERT INTO Cosmetics (name, image, type, description)
VALUES
('Slave Handler', 'https://trendygwentleman.com/static/img/avatars/48450.jpg', 'avatar','Win 10 Draft matches'),
('Dagon', 'https://trendygwentleman.com/static/img/avatars/48425.jpg', 'avatar', 'Available from the Dagon seasonal reward tree'),
('Soldier Haircut', 'https://trendygwentleman.com/static/img/avatars/48103.jpg', 'avatar', 'Unlocked by reaching level 1 in Geralt''s Standard Journey'),
('Happy Ciri', 'https://trendygwentleman.com/static/img/avatars/48163.jpg', 'avatar', 'Unlocked by reaching level 1 in Ciri''s Standard Journey'),
('Ciri Nova', 'https://trendygwentleman.com/static/img/avatars/48159.jpg', 'avatar', 'Unlocked by reaching level 6 in Ciri''s Standard Journey'),
('Wild Hunt Pursuit Cardback', 'https://trendygwentleman.com/static/img/cb/600670.png', 'cardback', 'Unlocked by reaching level 12 in Ciri''s Standard Journey'),
('Kitsune', 'https://trendygwentleman.com/static/img/avatars/48162.jpg', 'avatar', 'Unlocked by reaching level 18 in Ciri''s Standard Journey'),
('Skellige Ciri', 'https://trendygwentleman.com/static/img/avatars/48161.jpg', 'avatar', 'Unlocked by reaching level 24 in Ciri''s Standard Journey'),
('Hooded Ciri', 'https://trendygwentleman.com/static/img/avatars/48158.jpg', 'avatar', 'Unlocked by reaching level 30 in Ciri''s Standard Journey'),
('Fire Possession Cardback', 'https://trendygwentleman.com/static/img/cb/600690.png', 'cardback', 'Unlocked by reaching level 36 in Ciri''s Standard Journey'),
('Ciri Kaer Morhen Adept', 'https://trendygwentleman.com/static/img/avatars/48157.jpg', 'avatar', 'Unlocked by reaching level 42 in Ciri''s Standard Journey'),
('Sack Mascote Ciri', 'https://trendygwentleman.com/static/img/avatars/48155.jpg', 'avatar', 'Unlocked by reaching level 48 in Ciri''s Standard Journey'),
('Downsize Ciri', 'https://trendygwentleman.com/static/img/avatars/48154.jpg', 'avatar', 'Unlocked by reaching level 54 in Ciri''s Standard Journey'),
('Purple Portal Animated Border', 'https://trendygwentleman.com/static/img/borders/38084.png', 'border', 'Unlocked by reaching level 60 in Ciri''s Standard Journey'),
('Sword Coin', 'https://trendygwentleman.com/static/img/c/70010.png', 'coin', 'Unlocked by reaching level 66 in Ciri''s Standard Journey'),
('Cirilla Fiona Elen Riannon', 'https://trendygwentleman.com/static/img/avatars/48156.jpg', 'avatar', 'Unlocked by reaching level 72 in Ciri''s Standard Journey'),
('Ciri', 'https://trendygwentleman.com/static/img/ls/80127.png', 'leader', 'Unlocked by reaching level 78 in Ciri''s Standard Journey'),
('LADY OF SPACE AND TIME', 'https://trendygwentleman.com/static/img/ls/85127.png', 'title', 'Unlocked by reaching level 84 in Ciri''s Standard Journey'),
('Last Farewell Cardback', 'https://trendygwentleman.com/static/img/cb/600700.png', 'cardback', 'Unlocked by reaching level 90 in Ciri''s Standard Journey'),
('Cat Pendant Coin', 'https://trendygwentleman.com/static/img/c/70009.png', 'coin', 'Unlocked by reaching level 96 in Ciri''s Standard Journey'),
('Oriental Ciri', 'https://trendygwentleman.com/static/img/avatars/48165.jpg', 'avatar', 'Unlocked by reaching level 100 in Ciri''s Standard Journey'),
('Royal Skin','https://trendygwentleman.com/static/img/ls/80015.png', 'leader', 'Default leader skin for Northern Realms faction'),
('Duke of Dogs Skin', 'https://trendygwentleman.com/static/img/ls/80085.png', 'leader', 'Leader skin available from Shupe'),
('Cursed Toad Border','https://trendygwentleman.com/static/img/borders/36102.png', 'border', 'Available from the Year of the Cursed Toad reward tree'),
('OF LYRIA', 'https://trendygwentleman.com/static/img/ls/85127.png', 'title', 'Available during Summer Cycle');
@@ -0,0 +1,32 @@
USE "Gwent - The Witcher Card Game"
INSERT INTO DecksCards (hDeck, hCard, nrOfCards)
VALUES ((SELECT hmy FROM Decks WHERE name = 'Northern Realms - Deck'),
(SELECT hmy FROM Cards WHERE name = 'Vysogota of Corvo'),
2
)
INSERT INTO DecksCards (hDeck, hCard, nrOfCards)
VALUES ((SELECT hmy FROM Decks WHERE name = 'Northern Realms - Deck'),
(SELECT hmy FROM Cards WHERE name = 'Blue Stripes Commando'),
1
)
INSERT INTO DecksCards (hDeck, hCard, nrOfCards)
VALUES ((SELECT hmy FROM Decks WHERE name = 'Northern Realms - Deck'),
(SELECT hmy FROM Cards WHERE name = 'Bloody Baron'),
2
)
INSERT INTO DecksCards (hDeck, hCard, nrOfCards)
VALUES ((SELECT hmy FROM Decks WHERE name = 'Nilfgaard - Deck'),
(SELECT hmy FROM Cards WHERE name = 'Collar'),
1
)
INSERT INTO DecksCards (hDeck, hCard, nrOfCards)
VALUES ((SELECT hmy FROM Decks WHERE name = 'Nilfgaard - Deck'),
(SELECT hmy FROM Cards WHERE name = 'Imperial Diviner'),
2
)
@@ -0,0 +1,46 @@
USE "Gwent - The Witcher Card Game"
INSERT INTO Decks (name, faction, strategem, nrOfCards, nrOfNeutralCards, owner)
VALUES ('Northern Realms - Deck',
(SELECT hmy FROM Factions WHERE name = 'Northern Realms'),
(SELECT hmy FROM Cards WHERE name = 'Engineering Solution'),
20,
5,
(SELECT hmy FROM Players WHERE name = 'Sif_Great_Wolf')
)
INSERT INTO Decks (name, faction, strategem, nrOfCards, nrOfNeutralCards, owner)
VALUES ('Nilfgaard - Deck',
(SELECT hmy FROM Factions WHERE name = 'Nilfgaard'),
(SELECT hmy FROM Cards WHERE name = 'Collar'),
20,
10,
(SELECT hmy FROM Players WHERE name = 'Sif_Great_Wolf')
)
INSERT INTO Decks (name, faction, strategem, nrOfCards, nrOfNeutralCards, owner)
VALUES ('Scoia''tael - Deck',
(SELECT hmy FROM Factions WHERE name = 'Scoia''tael'),
(SELECT hmy FROM Cards WHERE name = 'Magic Lamp'),
20,
0,
(SELECT hmy FROM Players WHERE name = 'Nik-r')
)
INSERT INTO Decks (name, faction, strategem, nrOfCards, nrOfNeutralCards, owner)
VALUES ('Monsters - Deck',
(SELECT hmy FROM Factions WHERE name = 'Monsters'),
(SELECT hmy FROM Cards WHERE name = 'Magic Lamp'),
20,
0,
(SELECT hmy FROM Players WHERE name = 'lerio2')
)
INSERT INTO Decks (name, faction, strategem, nrOfCards, nrOfNeutralCards, owner)
VALUES ('Skellige - Deck',
(SELECT hmy FROM Factions WHERE name = 'Skellige'),
(SELECT hmy FROM Cards WHERE name = 'Mask of Uroboros'),
20,
0,
(SELECT hmy FROM Players WHERE name = 'Mya-Mon369EX')
)
@@ -0,0 +1,10 @@
USE "Gwent - The Witcher Card Game"
INSERT INTO Factions(name, totalMatches, totalWins, totalLosses, totalDraws, totalCards)
VALUES('Neutral', 0, 0, 0, 0, 0),
('Monsters', 0, 0, 0, 0, 0),
('Nilfgaard', 0, 0, 0, 0, 0),
('Northern Realms', 0, 0, 0, 0, 0),
('Scoia''tael', 0, 0, 0, 0, 0),
('Skellige', 0, 0, 0, 0, 0),
('Syndicate', 0, 0, 0, 0, 0)
@@ -0,0 +1,691 @@
USE "Gwent - The Witcher Card Game"
DECLARE @level6 INT = (SELECT hmy FROM Cosmetics WHERE description like '% 6 in Ciri''s Standard Journey%');
DECLARE @level12 INT = (SELECT hmy FROM Cosmetics WHERE description like '% 12 in Ciri''s Standard Journey%');
DECLARE @level18 INT = (SELECT hmy FROM Cosmetics WHERE description like '% 18 in Ciri''s Standard Journey%');
DECLARE @level24 INT = (SELECT hmy FROM Cosmetics WHERE description like '% 24 in Ciri''s Standard Journey%');
DECLARE @level30 INT = (SELECT hmy FROM Cosmetics WHERE description like '% 30 in Ciri''s Standard Journey%');
DECLARE @level36 INT = (SELECT hmy FROM Cosmetics WHERE description like '% 36 in Ciri''s Standard Journey%');
DECLARE @level42 INT = (SELECT hmy FROM Cosmetics WHERE description like '% 42 in Ciri''s Standard Journey%');
DECLARE @level48 INT = (SELECT hmy FROM Cosmetics WHERE description like '% 48 in Ciri''s Standard Journey%');
DECLARE @level54 INT = (SELECT hmy FROM Cosmetics WHERE description like '% 54 in Ciri''s Standard Journey%');
DECLARE @level60 INT = (SELECT hmy FROM Cosmetics WHERE description like '% 60 in Ciri''s Standard Journey%');
DECLARE @level66 INT = (SELECT hmy FROM Cosmetics WHERE description like '% 66 in Ciri''s Standard Journey%');
DECLARE @level72 INT = (SELECT hmy FROM Cosmetics WHERE description like '% 72 in Ciri''s Standard Journey%');
DECLARE @level78 INT = (SELECT hmy FROM Cosmetics WHERE description like '% 78 in Ciri''s Standard Journey%');
DECLARE @level84 INT = (SELECT hmy FROM Cosmetics WHERE description like '% 84 in Ciri''s Standard Journey%');
DECLARE @level90 INT = (SELECT hmy FROM Cosmetics WHERE description like '% 90 in Ciri''s Standard Journey%');
DECLARE @level96 INT = (SELECT hmy FROM Cosmetics WHERE description like '% 96 in Ciri''s Standard Journey%');
DECLARE @level100 INT = (SELECT hmy FROM Cosmetics WHERE description like '% 100 in Ciri''s Standard Journey%');
INSERT INTO Journeys (storyPanel1, storyPanel2, storyPanel3, storyPanel4, storyPanel5, storyPanel6, storyPanel7, storyPanel8, storyPanel9, storyPanel10, storyPanel11, storyPanel12, level6Reward, level12Reward, level18Reward, level24Reward, level30Reward, level36Reward, level42Reward, level48Reward, level54Reward, level60Reward, level66Reward, level72Reward, level78Reward, level84Reward, level90Reward, level96Reward, level100Reward)
VALUES
(
'Wait, I forgot about the mugs! Let me just grab them from the saddle.
Okay, back to the fire. Now, where do I start? There was so much of it, uncle Vesemir. Its just hard to recall the first thing⁠—oh! I got it! Its not from our training or theory lessons though ...
Do you remember the fairy tale about the tabby cat and the red fox? The one where hunters wanted to tear their fur off? Make them into muffs? Of course you remember. How many times have you told it as a bedtime story to the kids of Kaer Morhen? Dozens? Hundreds? Even to Geralt, right? I just cant seem to imagine him as a child. Was he ever, really?
Okay, I know. He had to be.
Anyway, it was Geralt, who told me this fairy tale when I was just little. Ugh, I didn''t like it when others would call me "little" back then, and now here I am doing it myself. Well, thats the truth: I was little. And lost. And all alone. I had fled from King Ervylls men and his nasty son, Kistrin, whom I really, really didnt want to marry. I mean, his breath alone—eugh! Anyway … thats how I ended up lost in Brokilon forest. And thats where Id have died, if it wasnt for Geralt. If he hadnt shown up out of nowhere and killed this overgrown centipede … Oh, I know, I know! Not a centipede, but a yghern, also known as the scolopendromorph. However, you must admit, even in the engravings it looks just like an overgrown centipede.
So Geralt rescued me from the yghern, and later, when I was lying on the forest floor with the stars blinking at us through the crowns of trees, unable to fall asleep, he told me your bedtime story. About the cat and fox hunted down by humans. In a way, despite not having met yet, it was the first lesson you gave me. Its pretty good, by the way. While escaping, it''s usually better to act like a cat rather than try to be clever like a fox. Just quickly, react without a second thought, without trying some thousand two hundred and eighty-six plots to outsmart the hunter. Do one: hop up the tree. Run away. Dont look back.
Otherwise you end up as a piece of decorative fur. Like this red muff.',
'Who shall we toast to? Geralt? Cheers!
Whew, thats strong. Waters of Brokilon strong, heh.
You see, uncle Vesemir ... Already then, which feels like an eternity ago, I realized that I was meant for him. When he was telling the story of the cat and fox, I felt it clearly⁠—this power binding us together even more than the strongest of blood ties. But he turned out to be too stubborn to believe it back then. Dumber than a child lost in the wilderness, you understand? Of course you do. Ive heard you tell him how stupid he was yourself.
Indeed, uncle.
But back to your first lesson. The fairy tale.
You also used it as a bedtime story for me once. I woke up in the middle of the night, unable to sleep through those nightmares of mine. All alone in the dark ... Suddenly, I heard your voice, so warm and caring. The fear vanished at once, disappearing without a trace. You were telling the story differently from Geralt though—in more detail, yet not at all boring. That''s why I never said anything. Sorry to admit, but in the end, this particular teaching turned against the teacher himself.
Yes, you heard me right. Against you.
I was a bit⁠—or even a very—unruly child, but we both know you liked it. Although in this case I probably drove you crazy. Just a little.
It was when the monster from Brokilon had already become a vague memory, the ugly prince Kistrin completely forgotten, and when Cintra ... Cintra utterly ceased to be. The Witchers'' Keep became my home. And you, the big bad Wolves themselves, were my family. Yes, indeed, you know that very well. I guess Im stalling, sorry.
Erm, so ... do you remember that time I slipped away? No, not the first. Nor second.
Id already grown very fond of the place by this time. Sure, it wasnt much⁠—a bed, a trunk, and that huge, filthy rat I killed and kept as a trophy⁠—but Id never felt more at home. It was far from the comforts of my chambers in Cintra, sure, but given a choice ... Id have chosen Kaer Morhen every time.
So, why run away then, you ask?
I will tell you in a moment. But first, let''s pour some more of that brew.',
'I wont lie to you, uncle Vesemir. Fear overtook me upon seeing Kaer Morhen for the first time. I was scared as hell.
When Geralt found me after Cintra''s fall⁠—this time to finally take me with him⁠—I thought I would never feel fear again. That the worst was over ... But, instead of a home, I was in this dark, ruined castle, full of rats and nightmarish echoes. I saw menacing black figures. I saw evil, incredibly shiny eyes staring at me. Glowing in the dark. Suddenly, I heard your voice for the first time, warm and caring, and just like that, the fear had been vanquished. Black silhouettes became friends. Protectors. Glossy eyes expressed curiosity.
In fact, you all cared. Very much so.
But some things ... Only you were able to take care of. For instance, the leather jerkin you made for me. It was a little bit crooked ... Well, okay. Very crooked. Truth be told, it looked like the nightmare of any self-respecting tailor. But I still liked it, just as I liked the sword you forged me. Nobody in the keep—absolutely nobody!—forgot about my training. Not once. But only you remembered that a child, even one with my talents, needs proper clothing and a sword befitting her size. You really tried your best, and I appreciated it.
Maybe even too much?
If I hadnt wanted to repay you so eagerly, maybe Id have stayed on the Trail. Not run into the woods instead of sticking to my training. I just thought I''d be able to get back to the stronghold before anyone noticed my disappearance. You see, I''d heard a couple of times how much you wouldnt mind eating some venison. Sometimes you even mumbled under your breath: if only one of you younger witchers could kindly go hunting, we could have a feast. But nooo… Its just beans and beans, over and over again.
Well, I was young. And a witcher. Kind of. So I thought it would be a splendid idea to fulfill your wish. There was only one small concern ... that you may not quite acknowledge the accuracy of my reasoning, or worse⁠—youd have me polishing swords for the whole day, after hearing it. Because you cared, of course. About me and the swords. That''s why I decided it would be better to surprise you. With a delicious boar.
And I knew exactly where to find one …',
'No, not at all.
I didn''t go for this boar completely unprepared. I made snares ... All right. I admit. It was no Talgar Winter or even a Wolf Pit. Just a simple trap.
But it worked!
Well, okay. It almost worked. It sprung. Snap! Crash! However, the boar could somehow still move. Then … the huge beast charged.
Charged straight at me.
Still, I didn''t run away, uncle Vesemir. I bravely raised my sword, which you fitted so well to my hand. And then I boldly repeated everything that you all taught me during my training. Lunge, attack, retreat! Half-pirouette, blow, rebound! I balanced with one arm, cutting with the other, jumping over a slippery forest floor with roots reaching out from under the leaves.
The boar didnt give a damn about my pirouettes. Someone could even say that he reacted with admirable resistance. I stabbed his hairy rear at least once, but he didn''t even grunt. Then, suddenly, he lifted his head, kicked up dirt, and pivoted, charging straight at me again.
I stood my ground, ready to fight. Youd have been proud to see it.
Attack, bounce! Riposte! Half-pirouette! Riposte, full pirouette! Half-pirouette! Jump and cut!
But the damned swine didnt even blink. He looked me straight in the eye. Tenacious. What was I to do? My blows seemed ineffective. Pointless even. Like stabbing a sack of millet or a wooden log.
But no! One must remain calm⁠—breathe⁠—keep going. You taught me that. Stay focused, wait until the last possible moment to evade. Steady … Steady … Pirouette!
Unfortunately, that particular pirouette didnt work very well. And by this I mean: not at all. He hit me sideways⁠—thwack!—and I flew a good twenty feet into the air. I thumped my back against one of the trees and the sword flew from my hand. For a moment, Brokilon flashed before my eyes, together with the stars. The water rustled in my head.
And one thought: Escape! Run away like the cat from your story. Hop up the tree. Dont look back.
The boar was in no hurry. At first, he sniffed the sword lying in the dirt. Then he slowly raised his big bulky head towards me⁠—a small girl huddled in a tangle of branches. My ribs burned cruelly, every breath spreading through my body with dull pulsating pain.
He stood sentinel, this tenacious boar. Staring. Waiting calmly under the tree.
I don''t know how much time passed before he got bored. But it was enough for you to notice my absence.',
'As I waited for our would-be dinner to go away, I recalled the words of a nursery rhyme. You recited it in my mind:
“How doth the little wild boar
Improve his shining tusks,
And rut them ''gainst the forest floor,
And on the trees'' rough husks!
How cheerfully he seems to grin
How neatly spreads his claws,
And welcomes little lasses in,
With gently smiling jaws!”
Louis of Charolleis poem is another of many things I know thanks to you, uncle. Unfortunately, it turned out to be of little use in this situation.
Annoying, really.
Huddled in the large oak tree, I couldn''t keep your voice and rhymes out of my head. I had a hard time gathering my thoughts⁠—to come up with some plan. The sight of my muddied sword, trampled on by the boars hooves, didnt help my concentration. It frustrated me. What you would say, seeing the blade in such a state... I couldnt bear the thought! So, when I was sure the beast was gone for good, all that was left on my mind was the desire to get my weapon back.
I slowly slipped off the tree and took a few careful steps. My ribs still stung with each breath, and my heart thrashed like a bell.
Suddenly, I heard your voice.
No, not in my head, but for real. Getting closer. You screamed my name, but instead of joy it filled me with panic. I quickly plunged my hand into the undergrowth and grabbed the sword. Its blade shimmering beneath the filth. Then more shouting—my name ringing out all around. Shadows moved among the trees. From the darkness came louder and louder: Ciri! Cirilla!
Cirilla Fiona Elen Riannon. Princess of Cintra...
Suddenly, the nightmares came back, even though I was awake. There was a wall of fire before me. I saw a frightening black knight with a winged helmet. I heard the screams of Cintrians being slaughtered.
There was no “hop” this time.
Just like that, on an impulse, I appeared in the crown of some random pine tree. And then I fell. But just before I hit the ground, it happened again. Another pine tree. This time, I grabbed onto a branch before I plummeted like a stone. Miraculously, I somehow kept hold of my sword. Then I watched in amazement as you traced my footsteps all the way to the large oak tree. How you scratched your head when my trail just... disappeared.
Back then, I didn''t know what happened, but I think it was probably the first time I teleported.',
'How come you didnt hear about this before? Well, Geralt helped me. Although you were all looking, it was he who finally found me. As always. Destiny, huh?
I know, I know, it''s getting old. Just destiny and destiny, over and over again.
And beans, ha!
In any case, I was so confused as I watched you from atop the tree I should never have been in. The world seemed unreal. Time passed at a strange, altered pace. I don''t think I prophesied on this occasion, or you surely would have heard me.
But I had a vision...
A cat ran away with a skulk of foxes. She jumped, hop-hop, from tree to tree. The foxes raced down below. And hunters swarmed from behind. Blacks, reds, hounds, and even one really scary lion.
Needless to say, the foxes were turned into bloody muffs, while the cat ran and ran and ran away. It seemed she would never stop...
My eyes snapped open.
Geralt was leaning over me with a stern face, but the faintest of smiles betrayed his facade. He was angry with me, sure, but I was safe and that was most important to him.
Of course, I started talking pretty quickly. About leaving the Trail, about this grand plan of mine, about the trap that didnt quite work, and the stubborn boar that refused to yield. I just didn''t mention the strange jumps, or talk about the vision. I was afraid⁠—wanted to pretend it hadnt happened. I thought, instead of dwelling on such things, why not convince him of my original plan? After all, working together as a team, well... that boar wouldnt stand a chance!
Geralt disagreed. He said I had probably come across the Old Wild—the caring spirit of the forest. So… no boar. But we didnt leave empty-handed.
While returning to Kaer Morhen, we managed to hunt a hare along the way. It was small, skinny, and stringy, but the soup came out surprisingly tasty. You remember? No, of course not... You didn''t even notice the hare when we came back. You didn''t care about fatigue or hunger. You were more interested in me⁠—the fear that echoed in my voice and the bruising on my ribs. You immediately took care of my wounds and started brewing some healing potions.
You never touched the hare soup. Not even a taste. Instead, you made me eat it all to regain my strength.
',
'Fairy tales and nursery rhymes. All these fat volumes read together. Fencing lessons… Anything else? Hmm, maybe for a change something you didn''t teach me?
A lot of things. Right. But this is quite a crucial one.
Contrary to appearances, neither you nor Geralt showed me how to kill. How to defend myself, yes. To survive, sure. To not give up… But not how to take someone''s life in cold blood.
Because to fight is not the same as to kill. You know that well enough.
So you taught me how to swing a sword and to pirouette. How to dodge and block. Well, even how to attack! How to cut through a leather bag. A straw mannequin. An overgrown rodent. But not how to kill another human...
That I had to learn myself. Much later.
By the time of my first, I had long left Kaer Morhen. I had attained some basic education at the Temple of Melitele, where I received magical training under the supervision of Yennefer. But, once again, just as I started to warm to my new surroundings, I was whisked away to someplace else. This time, I found myself on the island of Thanedd.
During the coup.
I wont recount the whole incident for you, uncle. You already know the events well enough.
But it was terrible. One moment I was asleep in bed, the next I was kneeling among dead bodies. Suddenly, Thanedd became a second Cintra. People screamed, fought desperately, and died brutally before my eyes. Whether by sword or sorcery, death is ugly. So I ran from it. Especially as those I loved had disappeared. Left me to be hunted—again. And in the chaos, in this mad dash for my life, I found myself in Tor Lara. At the portal. It attracted me, summoned me, even whispered... And there was no other escape, only this shining oval. So, I closed my eyes and stepped into it. Then there was a blinding brightness and a furious whirlpool; a breathless blast that crushed my ribs and sucked the air from my lungs.
I ended up completely alone. In the middle of nowhere. The warped portal had spat me out in some random desert, where I was certain I would die. But I didnt. I found my way out—you know I somehow always do. Unfortunately, I ran straight into the hands of mercenary bandits…
It seemed no matter how far I ran, trouble would always find me. Capture looked to be my fate once more. And as we both know by now, its pretty hard to outrun destiny. But it was not to be. Thanks to the help of a skulk of foxes, I managed to escape.
I had always wondered when the foxes of my visions would show up, who theyd be, what theyd be like… As it happens, they turned out to be a rather violent hanza.
Yes, uncle. I want to tell you about a past that I''m not proud of at all. About deeds I have never fully forgiven myself for. About the time when I became a common bandit.
A Rat.',
'So, how did I join the hanza? Well, while the mercenaries who had captured me were feasting with another gang, the Rats attacked the inn. They did so because that other gang had imprisoned one of their companions⁠—had him tied up next to me.
Anyway, considering the circumstances, the Rats seemed like the best of two bad options, so I helped them⁠—to help myself.
Another fight broke out, as if the one on Thanedd wasn''t enough already. Along with the Rats, I ended up running away again.
That''s when... I...
I was racing through the village away from that damned inn, trying to escape the chaos.
Trying to avoid being captured at all costs.
Suddenly, one of the settlers emerged from a pigsty. He attacked me with a spear.
What happened next haunted my dreams for a long time. I remember everything. Every move. The instinctual half-turn that saved me from the spearhead, the settler that didnt have time to block my riposte⁠—my cut was simply too fast.
For a moment, I saw his mouth open, ready to scream. I saw an elongated bald forehead, pale above the line where a hat must have protected it from the sun. Now that paleness was spattered red. He howled and wheezed, fell and convulsed among the straw and dung. Blood spurted from him like a stuck pig, and my stomach rolled up into my throat.
I tried to justify what happened. Explained to myself that it was the fault of my training. Pure muscle memory. That I didn''t want to take anyone''s life. It was only self-defence.
And that was the truth... at least that first time.
Later, when I had officially joined the Rats, that changed. I changed. I started killing for reasons not worth killing for. Certainly not worth dying over.
But this didnt happen right away.
You could say I stalled for a long time. Pretended to be a killer in front of the others. During subsequent skirmishes and attacks, I used ferocious-looking blows during combat. Made them look deadly. But in reality, they were only meant to incapacitate. To overwhelm the opponent before death was necessary. Like that time with the bailiff transport...
We caught them near a fallen bridge. The Rats had killed the entire convoy, except for one soldier. The one that started to run away, but upon seeing me… turned his horse and rushed to attack… missing the mark. Even though he blocked, expecting a counter, I got him. A cut straight to the mouth. Not fatal, but nasty, just like the one that would eventually disfigure my face...
I wonder if he lived to tell someone his story?
I really hope so.',
'As you can see, uncle, people were eagerly jumping onto my sword. Maybe because I was the youngest Rat. Or I just looked the least threatening. Whatever the reason, death was a constant presence. Following my every step. Ahead of me. Surrounding me. Always in my hand.
I often thought about Kaer Morhen, especially at night. The home I wanted to return to with all my heart. But I was scared. I had lost so much on Thanedd, uncle. Or so I believed back then. I felt powerless.
I didnt want to forfeit what little I had left. End up all alone.
But I could hope… I suspected you might still be there. I dreamed of returning to the stronghold—seeing your warm smile upon my arrival. I charted maps and trails in my mind, wishing to make it so. But you know how it is. In times of war, loneliness on the road means a swift and brutal death.
And I didnt want to die. So I clung to my colourful gang. Hid within their ranks like a real rat. Just… went through the motions to get by.
Until the night we attacked the village of New Forge.
We snuck in with a single purpose: set fire to the mayors house. Burn it to the ground. You see, he was the fool who gave our companion to the mercenaries—the ones from the tavern. And we needed people to know that punishment for such an offence was inevitable. The penalty…? Death, of course.
But you must understand, uncle, it wasnt all villainy. The Rats reputation was just as good as bad. For we—the children of contempt—shared most of our spoils. We distributed cattle, grain, and cloths from the Nilfgaardians to the villages. Helped people. We paid handfuls of gold and silver to tailors and craftsmen for what we cherished above all else—weapons, clothing, and ornaments. And in return for our generosity, they fed us. Hosted us. Hid us. And even when smitten to a bloodied pulp, they didnt reveal our hideouts. They were loyal.
Eventually, the prefects placed a hefty reward on our heads.
Those with more greed than sense started to go fishing for Nilfgaardian gold. Just like the mayor of New Forge, who was blinded by his lust for coin, sealing his fate and condemning his own village to ruin in the process.
But what happened that night… amid the flames and chaos… snapped me back to reality. Made me realise what was truly important. Convinced me that I had to leave the Rats as soon as possible.
If I could.',
'When we handed out gold, we were loud and flamboyant. Made a real show of it. But when we attacked, we did so like rats, or rather… like foxes. Quietly, treacherous, cunning.
That night, the first sound to break the silence was the crackle of flames. Then it all got so loud. Screams of people fleeing the fire, shouting and wailing. Our mounts, accustomed to such noises, barely reacted to the commotion. The first survivors ran out of a smoking hut. Servants, by the look of their garb. We unsheathed our blades. Whoever the fire couldnt fry, we were to finish off with our own hands.
Suddenly, a ruckus broke out at the back of the house. Riders spilled from a hidden stable. Among them was the mayor, wearing nothing but his pants. His fat, naked belly bouncing as he rode. Since the servants didnt really matter to us, we chased down our main target, along with his kin. There were many of them—the mayor apparently lived with his entire family, even his fifth cousin on the distaff side, no doubt. Each Rat had more than enough targets.
I had two.
One on a big strong gelding, the other on a slender filly. The larger rider sat firmly in the saddle, the smaller one could barely hold on to the mount. I galloped after them, swallowing acrid air. They were within arms reach when the wind blew their hoods down. They glanced at me, their flowing hair red in the glow of the fire. Smoke wafted from the flames, and I choked. Coughed wildly until tears welled up in my eyes. I wiped them away to get a better look. I wasnt sure if Id just imagined it⁠—or if it was a trick of the light—because… the bigger one, uncle… he looked just like you. And the smaller one was around my age. A kid, really.
I blocked their path, swinging my sword.
The older one took up the fight. And although he looked like you, he definitely didnt have your fencing skills. I bested him quickly, with little effort. I threw him from the saddle, pushed him to the ground, then instinctively asked: who are you? As if it mattered. The man began spewing out words chaotically, writhing like an eagle owl caught in a net. The kid clumsily slipped off his horse and clung to his chaperone, even though the old man told him to run away. But the little snot didnt want to leave his guardian.
Then it hit me.
Mentor and student. Like you and me.
The boy had to be the mayors child—had the same chubby face. But his look… his expression… reminded me of… me. Stubbornness, fear, pain. It was all painted across his young face. It mirrored my own from a time not so long ago. Because that night I had a different face. The face of a hunter. Just like those who had chased me long ago.
Now I was the pursuer. I hurt, I stole, I killed...
The sword fell from my numb fingers. My lips barely moved as I spoke the words: Go away… Run. Fuck off already!
The elder asked no questions, didnt attempt to make sense of my sudden change of heart. He quickly grabbed the kids hand and stuffed him into the saddle. Immediately after that, he jumped on his mount and urged both horses to a trot.
Motionless, I watched as they galloped away.
Behind me came the tortured howls of the boys family.',
'So, I decided to leave.
The next night, I collected what few belongings I had and slipped out of camp. I might die a lonely death on the road, but I had to take that chance. I wanted to return to Kaer Morhen. To find you, if not Geralt or Yennefer...
The leader of the gang stood in my way: Giselher.
He said he knew what I did. That I let the kid go free. And he didnt even blame me for that, but the kids mentor... he should have died. No adult should be spared. Otherwise, rumours will spread that the Rats can be crossed and afterwards, they will just smack your bottom and send you on your merry way. No, the punishment must be more severe. All traitors must pay with their blood. That was the code⁠—and the reason Giselher stood before me, sword raised.
But I wasnt a traitor. Not yet, at least.
The threat flashed in his eyes: return to camp or betray us. Live or die⁠—whats it to be? Because if I didnt retreat, a Rat would die that night. That was just the way of it. And if there was even the slightest chance it would be me, I might have raised my sword. Took up the fight. But he would lose for sure, uncle⁠—I was far more skilled. And I couldnt use my magic because back then I thought Id lost it for good. I couldnt simply jump behind his back and disappear into the night without a trace.
No, I had to make a choice: kill a Rat… or stay as one.
You see, uncle... Giselher had always treated me well. He never tried to hurt or take advantage of me. He shared his spoils. Supported us. Took care of our ragtag band of outcasts. The rest of the world could burn to cinders for all he cared, but not us… not his Rats.
I didnt raise my sword. I feigned a laugh—an artificial peace-maker. Told him to stop being so dramatic. Cant a girl go for a midnight stroll? Was that not allowed?
Giselher smiled crookedly. Then invited himself along on my improvised walk.
He never mentioned the kid and his mentor after that, though I assured him Id kill the old man the first chance I got. Fortunately, I never got that chance, even though I spent many more moons in the Rats company.
Weeks passed. Months. More banditry and bloodshed. Until the day came when I finally left them...
That was the day the Rats all died, uncle—the whole hanza. Even when I chose not to kill, death followed me every step of the way.
They were slaughtered by the lion from my vision: Leo Bonhart. A bounty hunter. A hired killer who took pleasure in doling out pain, who had his eye on me above all others. He was the scariest man I had ever met in my life. He turned my band, my little foxes, into... into trophies.
And I...
I need a short break, uncle. How about another drink, eh?
Last one, I promise.',
'I killed him, uncle... Bonhart, I mean.
Finally, after so much time had passed. After enduring pain, loss, humiliation. After running so far. To other worlds, even. Other times. And it seemed like I would never stop. Death behind me, in front of me, always in my hand. But you cant outrun destiny, not for long.
Fighting that son of a bitch... it was quite something, uncle. If you saw how I dealt with him, you would be so proud of me.
But that is a story for another time.
The fire is dying. My cup is empty, yours... quite full. And I would like to tell you about the final lesson you gave me.
Someday you have to stop running away. Even if your loved ones shout the opposite.
My grandmother, Geralt, Yen... you. You all told me to run away. So I ran away. I ran from Cintra and Brokilon, from Thanedd and Tir ná Lia. I ran from hunters and assassins, elves and humans, blacks and reds. I didnt want to endanger my loved ones, so I escaped to other worlds. I thought youd all finally be safe if I left you alone. But you still searched for me. Relentlessly. Because thats how love works. Because when you love someone, you tell them to flee. You gladly face the danger alone, knowing that they are safe.
But it was my fight as well, uncle. Not just yours.
In my darkest moments, it was the memory of your care that helped me keep my humanity. But there is so much darkness in this world. You could never have kept me from it⁠—it never works out that way. Evil will always catch up with you. Death will eventually overtake you, surround you. Until you face it. Together with your loved ones... and for your loved ones.
It took me a long time to comprehend. And so much blood had to flow before I did. Your blood too, uncle. I had to lose you to understand.
Because thats when I finally decided to stop running. A year ago.
When you died.
When I was still a child⁠—a little witcher in a ruined castle full of rats and scary echoes⁠—you said you would not live forever. That you would soon rest in a shallow grave. But no one really believed you. Took it to heart.
You were eternal to us. Indestructible.
Taught us all so much.
Thats why Im here, on the anniversary of your death, paying you tribute by these fading embers, in the shadow of the ruins of your beloved Keep.
Because even though you are not here in body, you will always be here in spirit, living on through the wisdom you shared and the love you gave.
Eternal, after all...
Farewell, Vesemir, last master of Kaer Morhen.
My mentor.
Goodbye, old friend...
I will never stop missing you.',
@level6,
@level12,
@level18,
@level24,
@level30,
@level36,
@level42,
@level48,
@level54,
@level60,
@level66,
@level72,
@level78,
@level84,
@level90,
@level96,
@level100
)
@@ -0,0 +1,23 @@
USE "Gwent - The Witcher Card Game"
INSERT INTO JourneyProgress (hPlayer, hJourney, level)
VALUES(
(SELECT hmy FROM Players WHERE name = 'Sif_Great_Wolf'),
(SELECT hmy FROM Journeys),
100
),
(
(SELECT hmy FROM Players WHERE name = 'Nik-r'),
(SELECT hmy FROM Journeys),
100
),
(
(SELECT hmy FROM Players WHERE name = 'lerio2'),
(SELECT hmy FROM Journeys),
54
),
(
(SELECT hmy FROM Players WHERE name = 'RaChid-bhk'),
(SELECT hmy FROM Journeys),
74
)
@@ -0,0 +1,63 @@
USE "Gwent - The Witcher Card Game"
DECLARE @monster INT = (SELECT hmy FROM Factions WHERE name = 'Monsters')
DECLARE @nilfgaard INT = (SELECT hmy FROM Factions WHERE name = 'Nilfgaard')
DECLARE @northern_realms INT = (SELECT hmy FROM Factions WHERE name = 'Northern Realms')
DECLARE @scoiatael INT = (SELECT hmy FROM Factions WHERE name = 'Scoia''tael')
DECLARE @skellige INT = (SELECT hmy FROM Factions WHERE name = 'Skellige')
DECLARE @syndicate INT = (SELECT hmy FROM Factions WHERE name = 'Syndicate')
DECLARE @neutral INT = (SELECT hmy FROM Factions WHERE name = 'Neutral')
DECLARE @player1 INT = (SELECT hmy FROM Players WHERE name = 'Sif_Great_Wolf')
DECLARE @player2 INT = (SELECT hmy FROM Players WHERE name = 'Nik-r')
DECLARE @player3 INT = (SELECT hmy FROM Players WHERE name = 'lerio2')
DECLARE @player4 INT = (SELECT hmy FROM Players WHERE name = 'Mya-Mon369EX')
DECLARE @player5 INT = (SELECT hmy FROM Players WHERE name = 'Daniel.Cujba.54')
DECLARE @player6 INT = (SELECT hmy FROM Players WHERE name = 'RaChid-bhk')
INSERT INTO Matches (hPlayer1, hPlayer2, hPlayer1Faction, hPlayer2Faction, result)
VALUES
(@player1, @player2, @monster, @nilfgaard, 1),
(@player1, @player3, @monster, @northern_realms, 1),
(@player1, @player4, @monster, @scoiatael, 2),
(@player1, @player5, @monster, @skellige, 2),
(@player1, @player6, @monster, @syndicate, 1),
(@player2, @player3, @nilfgaard, @northern_realms, 3),
(@player2, @player4, @nilfgaard, @scoiatael, 1),
(@player2, @player5, @nilfgaard, @skellige, 1),
(@player2, @player6, @nilfgaard, @syndicate, 1),
(@player3, @player4, @northern_realms, @scoiatael, 2),
(@player3, @player5, @northern_realms, @skellige, 2),
(@player3, @player6, @northern_realms, @syndicate, 2),
(@player4, @player5, @scoiatael, @skellige, 2),
(@player4, @player6, @scoiatael, @syndicate, 1),
(@player5, @player6, @skellige, @syndicate, 2),
(@player1, @player2, @monster, @nilfgaard, 1),
(@player1, @player3, @monster, @northern_realms, 1),
(@player1, @player4, @monster, @scoiatael, 1),
(@player1, @player5, @monster, @skellige, 3),
(@player1, @player6, @monster, @syndicate, 3),
(@player2, @player3, @nilfgaard, @northern_realms, 1),
(@player2, @player4, @nilfgaard, @scoiatael, 3),
(@player2, @player5, @nilfgaard, @skellige, 1),
(@player2, @player6, @nilfgaard, @syndicate, 1),
(@player3, @player4, @northern_realms, @scoiatael, 1),
(@player3, @player5, @northern_realms, @skellige, 1),
(@player3, @player6, @northern_realms, @syndicate, 1),
(@player4, @player5, @scoiatael, @skellige, 1),
(@player4, @player6, @scoiatael, @syndicate, 1),
(@player5, @player6, @skellige, @syndicate, 2),
(@player1, @player2, @monster, @nilfgaard, 2),
(@player1, @player3, @monster, @northern_realms, 2),
(@player1, @player4, @monster, @scoiatael, 2),
(@player1, @player5, @monster, @skellige, 2),
(@player1, @player6, @monster, @syndicate, 1),
(@player2, @player3, @nilfgaard, @northern_realms, 1),
(@player2, @player4, @nilfgaard, @scoiatael, 1),
(@player2, @player5, @nilfgaard, @skellige, 2),
(@player2, @player6, @nilfgaard, @syndicate, 2),
(@player3, @player4, @northern_realms, @scoiatael, 1),
(@player3, @player5, @northern_realms, @skellige, 1),
(@player3, @player6, @northern_realms, @syndicate, 1),
(@player4, @player5, @scoiatael, @skellige, 2),
(@player4, @player6, @scoiatael, @syndicate, 1)
@@ -0,0 +1,10 @@
USE "Gwent - The Witcher Card Game"
INSERT INTO Players(name, totalMatches, totalWins, totalLosses, totalDraws, reward_points, scraps, ores, meteorite_powder, rank)
VALUES
('Sif_Great_Wolf', 680, 430, 238 ,12, 1241, 543,654,534,0),
('Nik-r', 572, 372, 194, 6, 534, 5355, 6546, 22, 0),
('lerio2',310, 210, 94, 6, 532, 654, 636, 367, 0),
('Mya-Mon369EX', 574, 363, 205, 6, 432, 543, 5235, 6543, 0),
('Daniel.Cujba.54', 0,0,0,0,0,10170,47,985,25),
('RaChid-bhk', 56,19,22,15,443,656,255,543,11)
@@ -0,0 +1,31 @@
SELECT * FROM CARDS
INSERT INTO Cards(name, faction, description, action, image, cost, power, color, type, cardset)
VALUES ('test', 65436, 'test', 'test', 'test', 100, 1000, 'test', 'test', 3000)
DELETE FROM Cards
WHERE name like '%test%'
-- 1. Delete all cards that are part of the Syndicate faction.
DELETE FROM Cards
WHERE faction = (SELECT hmy FROM Factions WHERE name = 'Syndicate');
-- 2. Delete all cards that have a cost of 0 and are not stratageum cards.
DELETE FROM Cards
WHERE cost = 0 AND type <> 'stratagem';
-- 1. Update the cost of all Syndicate cards to be one more than their current cost.
UPDATE Cards
SET cost = cost + 1
WHERE faction = (SELECT hmy FROM Factions WHERE name = 'Syndicate');
-- 2. Update the power of all special cards and stratagem cards to be null.
UPDATE Cards
SET power = NULL
WHERE type NOT IN ('unit', 'leader');
-- 3. Update the bronze cards that have a cost between 6 and 8 to be gold.
UPDATE Cards
SET color = 'gold'
WHERE color = 'bronze' AND cost BETWEEN 6 AND 8;
@@ -0,0 +1,250 @@
--2 queries with the union operation; use UNION [ALL] and OR;
-- 1. Find the names of all the cards that are either gold or have a power of 8 or greater.
SELECT name
FROM Cards
WHERE color = 'gold'
UNION
SELECT name
FROM Cards
WHERE power >= 8;
-- 2. Find the names of all the cards that are either bronze or have a power of 7 or less.
SELECT name
FROM Cards
WHERE color = 'bronze' OR power <= 7;
--2 queries with the intersection operation; use INTERSECT and IN;
-- 1. Find the names of all the cards that are both gold and are unit cards.
SELECT name
FROM Cards
WHERE color = 'gold'
INTERSECT
SELECT name
FROM Cards
WHERE type = 'unit';
-- 2. Find the names of all the cards that are both bronze and are special cards.
SELECT name
FROM Cards
WHERE color = 'bronze' and name IN
(SELECT name
FROM Cards
WHERE type = 'special');
--2 queries with the difference operation; use EXCEPT and NOT IN;
-- 1. Find the names of all the cards that are not used in any deck.
SELECT name
FROM Cards
EXCEPT
SELECT name
FROM Cards
WHERE name IN
(SELECT name
FROM CardsOwnership);
-- 2. Find the names of all cosmetics not owned by lerio2
SELECT name
FROM Cosmetics
WHERE hmy NOT IN
(SELECT hCosmetic
FROM CosmeticsOwnership
WHERE hPlayer = (SELECT hmy FROM Players WHERE name = 'lerio2'));
-- 4 queries with INNER JOIN, LEFT JOIN, RIGHT JOIN, and FULL JOIN (one query per operator); one query will join at least 3 tables, while another one will join at least two many-to-many relationships;
-- 1. Find all player and their decks.
SELECT p.name, d.name
FROM Decks d
RIGHT JOIN Players p ON p.hmy = d.owner;
-- 2. Find the names of each player, faction they played with and the result of the match.
SELECT p.name as Player1, f.name as Faction1, m.result, p2.name as Player2, f2.name as Faction2
FROM Matches m
INNER JOIN Players p ON m.hPlayer1 = p.hmy
INNER JOIN Factions f ON m.hPlayer1Faction = f.hmy
INNER JOIN Players p2 ON m.hPlayer2 = p2.hmy
INNER JOIN Factions f2 ON m.hPlayer2Faction = f2.hmy;
-- 3. Find the names of all cards and the decks they are used in.
SELECT c.name, d.name
FROM Cards c
LEFT JOIN DecksCards dc ON c.hmy = dc.hCard
LEFT JOIN Decks d ON dc.hDeck = d.hmy;
-- 4. Find the relationship between players and their cosmetics.
SELECT p.name, c.name
FROM Players p
FULL JOIN CosmeticsOwnership co ON p.hmy = co.hPlayer
FULL JOIN Cosmetics c ON co.hCosmetic = c.hmy;
-- 2 queries with the IN operator and a subquery in the WHERE clause; in at least one case, the subquery must include a subquery in its own WHERE clause;
-- 1. Find the names of all the cards that are used in any deck.
SELECT name
FROM Cards
WHERE hmy IN
(SELECT hCard
FROM DecksCards);
-- 2. Find the names of all the cards that are used in any deck owned by Sif_Great_Wolf.
SELECT name
FROM Cards
WHERE hmy IN
(SELECT hCard
FROM DecksCards
WHERE hDeck IN
(SELECT hmy
FROM Decks
WHERE owner = (SELECT hmy FROM Players WHERE name = 'Sif_Great_Wolf')));
-- 2 queries with the EXISTS operator and a subquery in the WHERE clause;
-- 1. Find the names of all the players that have at least one deck.
SELECT p.name
FROM Players p
WHERE EXISTS
(SELECT d.hmy
FROM Decks d
WHERE d.owner = p.hmy);
-- 2. Find all the players that have started the journey
SELECT p.name
FROM Players p
WHERE EXISTS
(SELECT j.hPlayer
FROM JourneyProgress j
WHERE j.hPlayer = p.hmy)
-- 2 queries with a subquery in the FROM clause;
-- 1. Find the decks of all pro players
SELECT DISTINCT d.name
FROM (
SELECT *
FROM Players
WHERE rank = 0
) as proPlayers
INNER JOIN Decks d on d.owner = proPlayers.hmy
-- 2. Find the decks of all active players
SELECT DISTINCT d.name
FROM (
SELECT *
FROM Players
WHERE totalMatches <> 0
) as activePlayers
INNER JOIN Decks d on d.owner = activePlayers.hmy
-- 4 queries with the GROUP BY clause, 3 of which also contain the HAVING clause; 2 of the latter will also have a subquery in the HAVING clause; use the aggregation operators: COUNT, SUM, AVG, MIN, MAX;
-- 1. Calculate the total number of unit cards
SELECT COUNT(*)
FROM Cards
GROUP BY type
HAVING type = 'unit';
-- 2. Calculate the average number of cards in a deck
SELECT AVG(cardCount)
FROM (
SELECT COUNT(*) as cardCount
FROM DecksCards
GROUP BY hDeck
) as cardCounts;
-- 3. Calculate the average cost of special cards
SELECT AVG(cost)
FROM Cards
GROUP BY type
HAVING type = 'special';
-- 4. Calculate the minimum power of a unit card
SELECT MIN(power)
FROM Cards
GROUP BY type
HAVING type = 'unit';
-- 4 queries using ANY and ALL to introduce a subquery in the WHERE clause (2 queries per operator); rewrite 2 of them with aggregation operators, and the other 2 with IN / [NOT] IN.
-- 1. Find the names of all the cards that are used in any deck.
SELECT name
FROM Cards
WHERE hmy IN
(SELECT hCard
FROM DecksCards);
SELECT name
FROM Cards
WHERE hmy = ANY
(SELECT hCard
FROM DecksCards);
-- 2. Find the cards that have the minimum cost
SELECT name
FROM Cards
WHERE cost <= ALL(SELECT cost FROM Cards);
SELECT name
FROM Cards
WHERE cost <= (SELECT MIN(cost) FROM Cards);
-- 3. Find the names of all the cards that are used in any deck owned by Sif_Great_Wolf.
SELECT name
FROM Cards
WHERE hmy IN
(SELECT hCard
FROM DecksCards
WHERE hDeck IN
(SELECT hmy
FROM Decks
WHERE owner = (SELECT hmy FROM Players WHERE name = 'Sif_Great_Wolf')));
SELECT name
FROM Cards
WHERE hmy = ANY
(SELECT hCard
FROM DecksCards
WHERE hDeck = ANY
(SELECT hmy
FROM Decks
WHERE owner = (SELECT hmy FROM Players WHERE name = 'Sif_Great_Wolf')));
-- 4. Find the player that has the biggest level in the Ciri journey
SELECT name
FROM Players
WHERE hmy >= ALL(
SELECT hPlayer
FROM JourneyProgress
WHERE hJourney = 1);
SELECT name
FROM Players
WHERE hmy >= (SELECT MAX(hPlayer) FROM JourneyProgress WHERE hJourney = 1);
@@ -0,0 +1,218 @@
-- Write SQL scripts that:
-- a. modify the type of a column;
-- b. add / remove a column;
-- c. add / remove a DEFAULT constraint;
-- d. add / remove a primary key;
-- e. add / remove a candidate key;
-- f. add / remove a foreign key;
-- g. create / drop a table.
-- For each of the scripts above, write another one that reverts the operation. Place each script in a stored procedure. Use a simple, intuitive naming convention.
-- a. modify the type of a column;
CREATE PROCEDURE setNameToVarChar100
AS
BEGIN
ALTER TABLE Decks
ALTER COLUMN name VARCHAR(100)
END
GO
CREATE PROCEDURE setNameToVarChar255
AS
BEGIN
ALTER TABLE Decks
ALTER COLUMN name VARCHAR(255)
END
GO
-- b. add / remove a column;
CREATE PROCEDURE addColumnDescription
AS
BEGIN
ALTER TABLE Decks
ADD description VARCHAR(255)
END
GO
CREATE PROCEDURE removeColumnDescription
AS
BEGIN
ALTER TABLE Decks
DROP COLUMN description
END
GO
-- c. add / remove a DEFAULT constraint;
CREATE PROCEDURE addDefaultToDescription
AS
BEGIN
ALTER TABLE Decks
ADD CONSTRAINT DF_Decks_description DEFAULT 'No description' FOR description
END
GO
CREATE PROCEDURE removeDefaultFromDescription
AS
BEGIN
ALTER TABLE Decks
DROP CONSTRAINT DF_Decks_description
END
GO
-- d. add / remove a primary key;
CREATE PROCEDURE removePrimaryKeyFromJournalProgress
AS
BEGIN
ALTER TABLE JourneyProgress
DROP CONSTRAINT PK__JourneyP__2FA1EA2E0A91C8BD
END
GO
CREATE PROCEDURE addPrimaryKeyToJournalProgress
AS
BEGIN
ALTER TABLE JourneyProgress
ADD CONSTRAINT PK__JourneyP__2FA1EA2E0A91C8BD PRIMARY KEY(hJourney, hPlayer)
END
GO
-- e. add / remove a candidate key;
CREATE PROCEDURE addCandidateKeyToDecks
AS
BEGIN
ALTER TABLE Decks
ADD CONSTRAINT CK_Decks_name UNIQUE(name)
END
GO
CREATE PROCEDURE removeCandidateKeyFromDecks
AS
BEGIN
ALTER TABLE Decks
DROP CONSTRAINT CK_Decks_name
END
GO
-- f. add / remove a foreign key;
CREATE PROCEDURE removeForeignKeyFromJourneyProgress
AS
BEGIN
ALTER TABLE JourneyProgress
DROP CONSTRAINT FK__JourneyPr__hPlay__031C6FA4
END
GO
CREATE PROCEDURE addForeignKeyToJourneyProgress
AS
BEGIN
ALTER TABLE JourneyProgress
ADD CONSTRAINT FK__JourneyPr__hPlay__031C6FA4 FOREIGN KEY(hPlayer) REFERENCES Players(hmy)
END
GO
-- g. create / drop a table.
CREATE PROCEDURE createTableSkillTree
AS
BEGIN
CREATE TABLE SkillTree(
hmy INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description VARCHAR(8000) NOT NULL,
hFaction INT NOT NULL references Factions(hmy),
hPlayer INT NOT NULL references Players(hmy),
)
END
GO
CREATE PROCEDURE dropTableSkillTree
AS
BEGIN
DROP TABLE SkillTree
END
GO
CREATE TABLE versionTable(
version INT NOT NULL
)
CREATE TABLE proceduresTable(
fromVersion INT NOT NULL,
toVersion INT NOT NULL,
procedureName VARCHAR(255) NOT NULL
PRIMARY KEY(fromVersion, toVersion)
)
INSERT INTO versionTable(version) VALUES(1)
INSERT INTO proceduresTable(fromVersion, toVersion, procedureName)
VALUES
(1, 2, 'setNameToVarChar100'),
(2, 1, 'setNameToVarChar255'),
(2, 3, 'addColumnDescription'),
(3, 2, 'removeColumnDescription'),
(3, 4, 'addDefaultToDescription'),
(4, 3, 'removeDefaultFromDescription'),
(4, 5, 'removePrimaryKeyFromJournalProgress'),
(5, 4, 'addPrimaryKeyToJournalProgress'),
(5, 6, 'addCandidateKeyToDecks'),
(6, 5, 'removeCandidateKeyFromDecks'),
(6, 7, 'removeForeignKeyFromJourneyProgress'),
(7, 6, 'addForeignKeyToJourneyProgress'),
(7, 8, 'createTableSkillTree'),
(8, 7, 'dropTableSkillTree')
GO
CREATE PROCEDURE VersionSelector(@newVersion int)
AS
BEGIN TRANSACTION versionControl
BEGIN TRY
DECLARE @currentVersion int
DECLARE @procedureName VARCHAR(255)
SET @currentVersion = (SELECT version FROM versionTable)
IF @newVersion > (SELECT MAX(toVersion) FROM proceduresTable)
RAISERROR('Invalid version', 16, 1)
IF @newVersion < (SELECT MIN(toVersion) FROM proceduresTable)
RAISERROR('Invalid version', 16, 1)
WHILE @currentVersion > @newVersion
BEGIN
SET @procedureName = (SELECT procedureName FROM proceduresTable WHERE fromVersion = @currentVersion AND toVersion = @currentVersion - 1)
EXEC @procedureName
SET @currentVersion = @currentVersion - 1
END
WHILE @currentVersion < @newVersion
BEGIN
SET @procedureName = (SELECT procedureName FROM proceduresTable WHERE fromVersion = @currentVersion AND toVersion = @currentVersion + 1)
EXEC @procedureName
SET @currentVersion = @currentVersion + 1
END
UPDATE versionTable SET version = @newVersion
COMMIT TRANSACTION versionControl
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION versionControl
PRINT ERROR_PROCEDURE()
PRINT ERROR_MESSAGE()
END CATCH
EXECUTE VersionSelector 1
@@ -0,0 +1,480 @@
if exists (select * from dbo.sysobjects where id = object_id(N'[FK_TestRunTables_Tables]') and OBJECTPROPERTY(id, N'IsForeignKey') = 1)
ALTER TABLE [TestRunTables] DROP CONSTRAINT FK_TestRunTables_Tables
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[FK_TestTables_Tables]') and OBJECTPROPERTY(id, N'IsForeignKey') = 1)
ALTER TABLE [TestTables] DROP CONSTRAINT FK_TestTables_Tables
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[FK_TestRunTables_TestRuns]') and OBJECTPROPERTY(id, N'IsForeignKey') = 1)
ALTER TABLE [TestRunTables] DROP CONSTRAINT FK_TestRunTables_TestRuns
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[FK_TestRunViews_TestRuns]') and OBJECTPROPERTY(id, N'IsForeignKey') = 1)
ALTER TABLE [TestRunViews] DROP CONSTRAINT FK_TestRunViews_TestRuns
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[FK_TestTables_Tests]') and OBJECTPROPERTY(id, N'IsForeignKey') = 1)
ALTER TABLE [TestTables] DROP CONSTRAINT FK_TestTables_Tests
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[FK_TestViews_Tests]') and OBJECTPROPERTY(id, N'IsForeignKey') = 1)
ALTER TABLE [TestViews] DROP CONSTRAINT FK_TestViews_Tests
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[FK_TestRunViews_Views]') and OBJECTPROPERTY(id, N'IsForeignKey') = 1)
ALTER TABLE [TestRunViews] DROP CONSTRAINT FK_TestRunViews_Views
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[FK_TestViews_Views]') and OBJECTPROPERTY(id, N'IsForeignKey') = 1)
ALTER TABLE [TestViews] DROP CONSTRAINT FK_TestViews_Views
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[Tables]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [Tables]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[TestRunTables]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [TestRunTables]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[TestRunViews]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [TestRunViews]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[TestRuns]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [TestRuns]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[TestTables]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [TestTables]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[TestViews]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [TestViews]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[Tests]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [Tests]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[Views]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [Views]
GO
CREATE TABLE [Tables] (
[TableID] [int] IDENTITY (1, 1) NOT NULL ,
[Name] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [TestRunTables] (
[TestRunID] [int] NOT NULL ,
[TableID] [int] NOT NULL ,
[StartAt] [datetime] NOT NULL ,
[EndAt] [datetime] NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [TestRunViews] (
[TestRunID] [int] NOT NULL ,
[ViewID] [int] NOT NULL ,
[StartAt] [datetime] NOT NULL ,
[EndAt] [datetime] NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [TestRuns] (
[TestRunID] [int] IDENTITY (1, 1) NOT NULL ,
[Description] [nvarchar] (2000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[StartAt] [datetime] NULL ,
[EndAt] [datetime] NULL
) ON [PRIMARY]
GO
CREATE TABLE [TestTables] (
[TestID] [int] NOT NULL ,
[TableID] [int] NOT NULL ,
[NoOfRows] [int] NOT NULL ,
[Position] [int] NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [TestViews] (
[TestID] [int] NOT NULL ,
[ViewID] [int] NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [Tests] (
[TestID] [int] IDENTITY (1, 1) NOT NULL ,
[Name] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [Views] (
[ViewID] [int] IDENTITY (1, 1) NOT NULL ,
[Name] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE [Tables] WITH NOCHECK ADD
CONSTRAINT [PK_Tables] PRIMARY KEY CLUSTERED
(
[TableID]
) ON [PRIMARY]
GO
ALTER TABLE [TestRunTables] WITH NOCHECK ADD
CONSTRAINT [PK_TestRunTables] PRIMARY KEY CLUSTERED
(
[TestRunID],
[TableID]
) ON [PRIMARY]
GO
ALTER TABLE [TestRunViews] WITH NOCHECK ADD
CONSTRAINT [PK_TestRunViews] PRIMARY KEY CLUSTERED
(
[TestRunID],
[ViewID]
) ON [PRIMARY]
GO
ALTER TABLE [TestRuns] WITH NOCHECK ADD
CONSTRAINT [PK_TestRuns] PRIMARY KEY CLUSTERED
(
[TestRunID]
) ON [PRIMARY]
GO
ALTER TABLE [TestTables] WITH NOCHECK ADD
CONSTRAINT [PK_TestTables] PRIMARY KEY CLUSTERED
(
[TestID],
[TableID]
) ON [PRIMARY]
GO
ALTER TABLE [TestViews] WITH NOCHECK ADD
CONSTRAINT [PK_TestViews] PRIMARY KEY CLUSTERED
(
[TestID],
[ViewID]
) ON [PRIMARY]
GO
ALTER TABLE [Tests] WITH NOCHECK ADD
CONSTRAINT [PK_Tests] PRIMARY KEY CLUSTERED
(
[TestID]
) ON [PRIMARY]
GO
ALTER TABLE [Views] WITH NOCHECK ADD
CONSTRAINT [PK_Views] PRIMARY KEY CLUSTERED
(
[ViewID]
) ON [PRIMARY]
GO
ALTER TABLE [TestRunTables] ADD
CONSTRAINT [FK_TestRunTables_Tables] FOREIGN KEY
(
[TableID]
) REFERENCES [Tables] (
[TableID]
) ON DELETE CASCADE ON UPDATE CASCADE ,
CONSTRAINT [FK_TestRunTables_TestRuns] FOREIGN KEY
(
[TestRunID]
) REFERENCES [TestRuns] (
[TestRunID]
) ON DELETE CASCADE ON UPDATE CASCADE
GO
ALTER TABLE [TestRunViews] ADD
CONSTRAINT [FK_TestRunViews_TestRuns] FOREIGN KEY
(
[TestRunID]
) REFERENCES [TestRuns] (
[TestRunID]
) ON DELETE CASCADE ON UPDATE CASCADE ,
CONSTRAINT [FK_TestRunViews_Views] FOREIGN KEY
(
[ViewID]
) REFERENCES [Views] (
[ViewID]
) ON DELETE CASCADE ON UPDATE CASCADE
GO
ALTER TABLE [TestTables] ADD
CONSTRAINT [FK_TestTables_Tables] FOREIGN KEY
(
[TableID]
) REFERENCES [Tables] (
[TableID]
) ON DELETE CASCADE ON UPDATE CASCADE ,
CONSTRAINT [FK_TestTables_Tests] FOREIGN KEY
(
[TestID]
) REFERENCES [Tests] (
[TestID]
) ON DELETE CASCADE ON UPDATE CASCADE
GO
ALTER TABLE [TestViews] ADD
CONSTRAINT [FK_TestViews_Tests] FOREIGN KEY
(
[TestID]
) REFERENCES [Tests] (
[TestID]
),
CONSTRAINT [FK_TestViews_Views] FOREIGN KEY
(
[ViewID]
) REFERENCES [Views] (
[ViewID]
)
GO
@@ -0,0 +1,173 @@
USE "Gwent - The Witcher Card Game"
GO
CREATE OR ALTER PROCEDURE addToTables (@tableName VARCHAR(255)) AS
IF @tableName IN (SELECT Name FROM Tables)
BEGIN
PRINT 'Table already present in Tables'
RETURN
END
IF @tableName NOT IN (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES)
BEGIN
PRINT 'Table doesn''t exists'
RETURN
END
INSERT INTO Tables (Name) VALUES (@tableName)
GO
CREATE OR ALTER PROCEDURE addToViews (@viewName VARCHAR(255)) AS
IF @viewName IN (SELECT Name FROM Views)
BEGIN
PRINT 'View already present in Views'
RETURN
END
IF @viewName NOT IN (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS)
BEGIN
PRINT 'View doesn''t exists'
RETURN
END
INSERT INTO Views (Name) VALUES (@viewName)
GO
CREATE OR ALTER PROCEDURE addTests (@testName VARCHAR(255)) AS
IF @testName IN (SELECT Name FROM Tests)
BEGIN
PRINT 'Test already present in Tests'
RETURN
END
INSERT INTO Tests (Name) VALUES (@testName)
GO
CREATE OR ALTER PROCEDURE addTestTables (@testName VARCHAR(255), @tableName VARCHAR(255), @rows INT, @position INT) AS
IF @tableName NOT IN (SELECT Name FROM Tables)
BEGIN
PRINT 'Table not present in Tables'
RETURN
END
IF @testName NOT IN (SELECT Name FROM Tests)
BEGIN
PRINT 'Test not present in Tests'
RETURN
END
IF EXISTS(
SELECT 1 FROM TestTables tt JOIN Tests t on tt.TestID = t.TestID
WHERE t.Name = @testName and tt.Position = @position
)
BEGIN
PRINT 'Position already exists in TestTables for current test'
RETURN
END
INSERT INTO TestTables (TableID, TestID, NoOfRows, Position) VALUES
(
(SELECT TableID from Tables WHERE Name = @tableName),
(SELECT TestID from Tests WHERE Name = @testName),
@rows,
@position
)
GO
CREATE OR ALTER PROCEDURE addTestViews (@testName VARCHAR(255), @viewName VARCHAR(255)) AS
IF @viewName NOT IN (SELECT Name FROM Views)
BEGIN
PRINT 'View not present in Views'
RETURN
END
IF @testName NOT IN (SELECT Name FROM Tests)
BEGIN
PRINT 'Test not present in Tests'
RETURN
END
INSERT INTO TestViews (ViewID, TestID) VALUES
(
(SELECT ViewID from Views WHERE Name = @viewName),
(SELECT TestID from Tests WHERE Name = @testName)
)
GO
CREATE OR ALTER PROCEDURE runTest (@testName VARCHAR(255)) AS
DECLARE @startTime DATETIME
DECLARE @endTime DATETIME
DECLARE @insertStartTime DATETIME
DECLARE @insertEndTime DATETIME
DECLARE @selectStartTime DATETIME
DECLARE @selectEndTime DATETIME
DECLARE @table VARCHAR(255)
DECLARE @view VARCHAR(255)
DECLARE @noOfTables INT
DECLARE @noOfViews INT
DECLARE @offset INT
DECLARE @rows INT
DECLARE @testRunID INT
DECLARE @command VARCHAR(255)
INSERT INTO TestRuns (Description) VALUES
(
'Test run for ' + @testName
)
SET @testRunID =(SELECT MAX(TestRunID) FROM TestRuns)
SET @offset = 0
SET @noOfTables = (SELECT COUNT(*) FROM TestTables tt JOIN Tests t on tt.TestID = t.TestID WHERE t.Name = @testName)
SET @noOfViews = (SELECT COUNT(*) FROM TestViews tv JOIN Tests t on tv.TestID = t.TestID WHERE t.Name = @testName)
IF @testName NOT IN (SELECT Name FROM Tests)
BEGIN
PRINT 'Test not present in Tests'
RETURN
END
SET @startTime = GETDATE()
WHILE @offset < @noOfTables
BEGIN
SET @table = (SELECT tab.Name FROM TestTables tt JOIN Tests t on tt.TestID = t.TestID JOIN Tables tab on tt.TableID = tab.TableID WHERE t.Name = @testName ORDER BY tt.Position OFFSET @offset ROWS FETCH NEXT 1 ROWS ONLY)
EXEC ('delete from ' + @table)
SET @offset = @offset + 1
END
SET @offset = 0
WHILE @offset < @noOfTables
BEGIN
SET @table = (SELECT tab.Name FROM TestTables tt JOIN Tests t on tt.TestID = t.TestID JOIN Tables tab on tt.TableID = tab.TableID WHERE t.Name = @testName ORDER BY tt.Position DESC OFFSET @offset ROWS FETCH NEXT 1 ROWS ONLY)
SET @rows = (SELECT NoOfRows FROM TestTables tt JOIN Tests t on tt.TestID = t.TestID JOIN Tables tab on tt.TableID = tab.TableID WHERE t.Name = @testName ORDER BY tt.Position DESC OFFSET @offset ROWS FETCH NEXT 1 ROWS ONLY)
SET @insertStartTime = GETDATE()
SET @command = 'populate' + @table
EXEC @command @rows
SET @insertEndTime = GETDATE()
INSERT INTO TestRunTables (TestRunID, TableID, StartAt, EndAt) VALUES
(
@testRunID,
(SELECT TableID FROM Tables WHERE Name = @table),
@insertStartTime,
@insertEndTime
)
SET @offset = @offset + 1
END
SET @offset = 0
WHILE @offset < @noOfViews
BEGIN
SET @view = (SELECT v.Name FROM TestViews tv JOIN Tests t on tv.TestID = t.TestID JOIN Views v on tv.ViewID = v.ViewID WHERE t.Name = @testName ORDER BY tv.ViewID OFFSET @offset ROWS FETCH NEXT 1 ROWS ONLY)
SET @selectStartTime = GETDATE()
EXEC ('select * from ' + @view)
SET @selectEndTime = GETDATE()
INSERT INTO TestRunViews (TestRunID, ViewID, StartAt, EndAt) VALUES
(
@testRunID,
(SELECT ViewID FROM Views WHERE Name = @view),
@selectStartTime,
@selectEndTime
)
SET @offset = @offset + 1
END
SET @endTime = GETDATE()
UPDATE TestRuns SET StartAt = @startTime, EndAt = @endTime WHERE TestRunID = @testRunID
SELECT * FROM TestRuns
SELECT * FROM TestRunTables
SELECT * FROM TestRunViews
@@ -0,0 +1,29 @@
USE "Gwent - The Witcher Card Game"
GO
CREATE OR ALTER PROCEDURE populateFactions (@rows INT) AS
WHILE @rows > 0
BEGIN
INSERT INTO Factions(name, totalMatches, totalWins, totalLosses, totalCards, totalDraws)
VALUES ('test', -1, -1, -1, -1, -1)
SET @rows = @rows - 1
END
GO
CREATE OR ALTER VIEW getNameAndTotalMatches AS
SELECT name, totalMatches
FROM Factions
GO
EXEC addTests 'test1'
EXEC addToTables 'Factions'
EXEC addToViews 'getNameAndTotalMatches'
EXEC addTestTables 'test1', 'Factions', 1000, 1
EXEC addTestViews 'test1', 'getNameAndTotalMatches'
GO
EXEC runTest 'test1'
@@ -0,0 +1,94 @@
USE "Gwent - The Witcher Card Game"
GO
CREATE OR ALTER PROCEDURE populateFactions (@rows INT) AS
WHILE @rows > 0
BEGIN
INSERT INTO Factions(name, totalMatches, totalWins, totalLosses, totalCards, totalDraws)
VALUES ('test', -1, -1, -1, -1, -1)
SET @rows = @rows - 1
END
GO
CREATE OR ALTER PROCEDURE populatePlayers (@rows INT) AS
WHILE @rows > 0
BEGIN
INSERT INTO Players(name, totalMatches, totalWins, totalLosses, totalDraws, reward_points, scraps, ores, meteorite_powder, rank)
VALUES ('test', -1, -1, -1, -1, -1, -1, -1, -1, -1)
SET @rows = @rows - 1
END
GO
CREATE OR ALTER PROCEDURE populateCardSet (@rows INT) AS
WHILE @rows > 0
BEGIN
INSERT INTO CardSet(name, image, releaseDate)
VALUES ('test', 'test', '2020-01-01')
SET @rows = @rows - 1
END
GO
CREATE OR ALTER PROCEDURE populateCards (@rows INT) AS
DECLARE @faction INT
SET @faction = (SELECT TOP 1 hmy FROM Factions)
DECLARE @cardset INT
SET @cardset = (SELECT TOP 1 hmy FROM CardSet)
WHILE @rows > 0
BEGIN
INSERT INTO Cards(name, faction, description, action, image, cost, type, power, color, cardset)
VALUES ('test', @faction, 'test', 'test', 'test', -1, 'unit', -1, 'gold', @cardset)
SET @rows = @rows - 1
END
GO
CREATE OR ALTER PROCEDURE populateCardsOwnership (@rows INT) AS
DECLARE @card INT
DECLARE @player INT
WHILE @rows > 0
BEGIN
SET @card = (SELECT hmy FROM Cards ORDER BY hmy OFFSET @rows ROWS FETCH NEXT 1 ROWS ONLY)
SET @player = (SELECT hmy FROM Players ORDER BY hmy OFFSET @rows ROWS FETCH NEXT 1 ROWS ONLY)
INSERT INTO CardsOwnership(hCard, hPlayer, nrOfCards, nrOfPremiumCards)
VALUES (@card, @player, 1, 1)
SET @rows = @rows - 1
END
GO
CREATE OR ALTER VIEW getNumberOfCardsOfEachTypeOwnByEachPlayer AS
SELECT p.name as Player, cs.Name as CardSet, Count(c.hmy) as NumberOfCards
FROM CardsOwnership co JOIN Cards c on co.hCard = c.hmy JOIN Players p on co.hPlayer = p.hmy JOIN CardSet cs on c.cardset = cs.hmy
GROUP BY p.name, cs.Name
GO
EXEC addTests 'test2'
EXEC addToTables 'Factions'
EXEC addToTables 'Players'
EXEC addToTables 'Matches'
EXEC addToTables 'CardSet'
EXEC addToTables 'Cards'
EXEC addToTables 'CardsOwnership'
EXEC addToViews 'getNumberOfCardsOfEachTypeOwnByEachPlayer'
EXEC addTestTables 'test2', 'Factions', 100, 6
EXEC addTestTables 'test2', 'Players', 1000, 5
EXEC addTestTables 'test2', 'CardSet', 10, 4
EXEC addTestTables 'test2', 'Matches', 10, 3
EXEC addTestTables 'test2', 'Cards', 1000, 2
EXEC addTestTables 'test2', 'CardsOwnership', 500, 1
EXEC addTestViews 'test2', 'getNumberOfCardsOfEachTypeOwnByEachPlayer'
GO
EXEC runTest 'test2'
@@ -0,0 +1,63 @@
USE "Gwent - The Witcher Card Game"
GO
CREATE OR ALTER PROCEDURE populateFactions (@rows INT) AS
WHILE @rows > 0
BEGIN
INSERT INTO Factions(name, totalMatches, totalWins, totalLosses, totalCards, totalDraws)
VALUES ('test', -1, -1, -1, -1, -1)
SET @rows = @rows - 1
END
GO
CREATE OR ALTER PROCEDURE populatePlayers (@rows INT) AS
WHILE @rows > 0
BEGIN
INSERT INTO Players(name, totalMatches, totalWins, totalLosses, totalDraws, reward_points, scraps, ores, meteorite_powder, rank)
VALUES ('test', -1, -1, -1, -1, -1, -1, -1, -1, -1)
SET @rows = @rows - 1
END
GO
CREATE OR ALTER PROCEDURE populateMatches (@rows INT) AS
DECLARE @player1 INT
SET @player1 = (SELECT TOP 1 hmy FROM Players)
DECLARE @player2 INT
SET @player2 = (SELECT TOP 1 hmy FROM Players WHERE hmy <> @player1)
DECLARE @faction INT
SET @faction = (SELECT TOP 1 hmy FROM Factions)
WHILE @rows > 0
BEGIN
INSERT INTO Matches(hPlayer1, hPlayer2, hPlayer1Faction, hPlayer2Faction, result)
VALUES (@player1, @player2, @faction, @faction, 1)
SET @rows = @rows - 1
END
GO
CREATE OR ALTER VIEW getMatches AS
SELECT p1.name as player1, p2.name as player2, f1.name as player1Faction, f2.name as player2Faction
FROM Matches m
JOIN Players p1 on m.hPlayer1 = p1.hmy
JOIN Players p2 on m.hPlayer2 = p2.hmy
JOIN Factions f1 on m.hPlayer1Faction = f1.hmy
JOIN Factions f2 on m.hPlayer2Faction = f2.hmy
GO
EXEC addTests 'test3'
EXEC addToTables 'Factions'
EXEC addToTables 'Players'
EXEC addToTables 'Matches'
EXEC addToViews 'getMatches'
EXEC addTestTables 'test3', 'Factions', 1000, 3
EXEC addTestTables 'test3', 'Players', 1000, 2
EXEC addTestTables 'test3', 'Matches', 1000, 1
EXEC addTestViews 'test3', 'getMatches'
GO
EXEC runTest 'test3'
@@ -0,0 +1,73 @@
-- Work on 3 tables of the form Ta(aid, a2, …), Tb(bid, b2, …), Tc(cid, aid, bid, …), where:
-- aid, bid, cid, a2, b2 are integers;
-- the primary keys are underlined;
-- a2 is UNIQUE in Ta;
-- aid and bid are foreign keys in Tc, referencing the primary keys in Ta and Tb, respectively.
-- a. Write queries on Ta such that their execution plans contain the following operators:
-- clustered index scan;
-- clustered index seek;
-- nonclustered index scan;
-- nonclustered index seek;
-- key lookup.
-- b. Write a query on table Tb with a WHERE clause of the form WHERE b2 = value and analyze its execution plan. Create a nonclustered index that can speed up the query. Examine the execution plan again.
-- c. Create a view that joins at least 2 tables. Check whether existing indexes are helpful; if not, reassess existing indexes / examine the cardinality of the tables.
--a. Write queries on Ta such that their execution plans contain the following operators:
-- clustered index scan;
--create unique constraint on name column
SELECT * FROM Players;
-- clustered index seek;
SELECT * FROM Players WHERE hmy = 22003;
-- nonclustered index seek;
-- add nonclustered index on name
CREATE NONCLUSTERED INDEX IX_Players_name ON Players(hmy, name) INCLUDE (totalMatches);
DROP INDEX IX_Players_name ON Players;
SELECT name, totalMatches FROM Players WHERE name = 'lerio2';
-- nonclustered index scan;
SELECT name, totalMatches FROM Players WHERE totalMatches > 0;
-- key lookup.
-- write a query that uses the nonclustered index and a key lookup
SELECT * FROM Players WHERE name = 'lerio2';
--b. Write a query on table Tb with a WHERE clause of the form WHERE b2 = value and analyze its execution plan. Create a nonclustered index that can speed up the query. Examine the execution plan again.
-- create nonclustered index on b2
CREATE NONCLUSTERED INDEX IX_Cards_faction_cardset ON Cards(hmy, faction, cardset) INCLUDE (name, cost);
DROP INDEX IX_Cards_faction_cardset ON Cards;
-- examine execution plan
SELECT hmy, name, cost, faction, cardset FROM Cards WHERE faction = (SELECT hmy FROM Factions WHERE name='Neutral') AND cardset = (SELECT hmy FROM CardSet WHERE name='Base Set');
--c. Create a view that joins at least 2 tables. Check whether existing indexes are helpful; if not, reassess existing indexes / examine the cardinality of the tables.
-- create view
GO
ALTER VIEW CardsOwners AS
SELECT Cards.name AS cardName, Players.name AS playerName, Cards.hmy AS cardId, Players.hmy AS playerId
FROM Cards
INNER JOIN CardsOwnership ON Cards.hmy = CardsOwnership.hCard
INNER JOIN Players ON Players.hmy = CardsOwnership.hPlayer
GO
-- check if indexes are helpful
SELECT * FROM CardsOwners;
@@ -0,0 +1,42 @@
USE "Gwent - The Witcher Card Game"
-- Drop all foreign keys
-- Drop all tables
DROP TABLE DecksCards
DROP TABLE Decks
DROP TABLE JourneyProgress
DROP TABLE Journeys
DROP TABLE CosmeticsOwnership
DROP TABLE Cosmetics
DROP TABLE Matches
DROP TABLE CardsOwnership
DROP TABLE Players
DROP TABLE Cards
DROP TABLE CardSet
DROP TABLE Factions
DELETE FROM DecksCards
DELETE FROM Decks
DELETE FROM JourneyProgress
DELETE FROM Journeys
DELETE FROM CosmeticsOwnership
DELETE FROM Cosmetics
DELETE FROM Matches
DELETE FROM CardsOwnership
DELETE FROM Players
DELETE FROM Cards
DELETE FROM CardSet
DELETE FROM Factions
DELETE FROM TestRunTables
DELETE FROM TestRunViews
DELETE FROM Tests
DELETE FROM TestRuns
DELETE FROM TestTables
DELETE FROM TestViews
DELETE FROM Views
DELETE FROM Tables
@@ -0,0 +1,63 @@
from time import sleep
import selenium
from selenium import webdriver
from selenium.webdriver.common.by import By
url = 'https://gwent.one/en/cards/?type=30&v=11.10.5'
driver = webdriver.Chrome()
driver.get(url)
sleep(1)
# Get all the cards
cards=[]
cards_ids=[]
new_cards = driver.find_elements(By.XPATH, "//div[contains(@class,'card-data')]")
i=1
while len(new_cards) > 0:
i+=1
cards += new_cards
cards_ids += [card.get_attribute("data-id") for card in new_cards]
driver.execute_script(f"ajaxSearch({i})")
sleep(3)
new_cards = driver.find_elements(By.XPATH, "//div[contains(@class,'card-data')]")
processed_cards = []
for id in cards_ids:
driver.get(f'https://gwent.one/en/card/{id}')
sleep(0.1)
card_data = driver.find_elements(By.XPATH, "//div[contains(@class,'card-data')]")
card_data = card_data[0]
name = card_data.find_element(By.XPATH, "//div[contains(@class,'card-name')]").text
faction = card_data.get_attribute("data-faction")
description = card_data.find_element(By.XPATH, "//div[contains(@class,'card-body-flavor')]").text
action = card_data.find_element(By.XPATH, "//div[contains(@class,'card-body-ability')]").text
image = card_data.find_element(By.XPATH, "//div[contains(@class,'card_asset-img')]/img").get_attribute("src")
provision = card_data.get_attribute("data-provision")
power = card_data.get_attribute("data-power")
color = card_data.get_attribute("data-color")
type = card_data.get_attribute("data-type")
cardSet = card_data.get_attribute("data-set")
processed_cards.append({
"name": name,
"faction": faction,
"description": description,
"action": action,
"image": image,
"provision": provision,
"power": power,
"color": color,
"type": type,
"cardSet": cardSet
})
print(len(processed_cards))
# Save to file to an Excel file
import pandas as pd
df = pd.DataFrame(processed_cards)
df.to_excel('cards.xlsx', index=False)
driver.close()
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,104 @@
package Controllers;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import Exceptions.BaseException;
import Models.Program.ProgramState;
import Models.Values.IValue;
import Models.Values.ReferenceValue;
import Repositories.IRepository;
public class Controller {
private IRepository repository;
private boolean displayFlag;
private ExecutorService executor;
public Controller(IRepository repository, boolean displayFlag) {
this.repository = repository;
this.displayFlag = displayFlag;
}
public List<ProgramState> removeCompletedPrograms(List<ProgramState> programStates) {
return programStates.stream().filter(p -> p.isNotCompleted()).collect(Collectors.toList());
}
public void oneStepForAllProgramStates(List<ProgramState> programStates) {
programStates.forEach(programState -> {
try{
repository.logProgramStateExecution(programState);
}
catch(BaseException e){
System.out.println(e.getMessage());
}
});
List<Callable<ProgramState>> callList = programStates.stream().map((ProgramState p) -> (Callable<ProgramState>)(() -> {
try{
return p.oneStep();
}
catch(BaseException e){
System.out.println(e.getMessage());
}
return null;
})).filter(c -> c != null).collect(Collectors.toList());
List<ProgramState> newProgramStates = new ArrayList<ProgramState>();
try{
newProgramStates = executor.invokeAll(callList).stream().map(future -> {
try {
return future.get();
} catch (Exception e) {
System.out.println(e.getMessage());
}
return null;
}).filter(p -> p != null).collect(Collectors.toList());
}
catch(InterruptedException e){
System.out.println(e.getMessage());
}
programStates.addAll(newProgramStates);
programStates.forEach(programState -> {
try{
repository.logProgramStateExecution(programState);
}
catch(BaseException e){
System.out.println(e.getMessage());
}
});
repository.setProgramStates(programStates);
}
public void allSteps() {
executor = Executors.newFixedThreadPool(2);
List<ProgramState> programStates = removeCompletedPrograms(repository.getProgramStates());
while(programStates.size() > 0){
programStates.get(0).getHeap().setContent(this.garbageCollector(this.getAddressesFromSymbolTable(programStates.stream().map(programState -> programState.getSymbolTable().getContent()).collect(Collectors.toList()), programStates.get(0).getHeap().getContent()), programStates.get(0).getHeap().getContent()));
oneStepForAllProgramStates(programStates);
programStates = removeCompletedPrograms(repository.getProgramStates());
}
executor.shutdownNow();
repository.setProgramStates(programStates);
}
public Hashtable<Integer, IValue> garbageCollector(Set<Integer> symbolTable, Hashtable<Integer, IValue> heap) {
return heap.entrySet().stream().filter(e -> symbolTable.contains(e.getKey()))
.collect(Hashtable::new, (m, e) -> m.put(e.getKey(), e.getValue()), Hashtable::putAll);
}
public Set<Integer> getAddressesFromSymbolTable(List<Collection<IValue>> symbolTablesValues, Hashtable<Integer, IValue> heap) {
return symbolTablesValues.stream().flatMap(Collection::stream).filter(v -> v instanceof ReferenceValue)
.flatMap(v -> Stream.iterate(((ReferenceValue) v).getAddress(), Objects::nonNull, addr -> {
var value = heap.get(addr);
return value instanceof ReferenceValue ? ((ReferenceValue) value).getAddress() : null;
})).distinct().collect(Collectors.toSet());
}
}
@@ -0,0 +1,7 @@
package Exceptions;
public class BaseException extends Throwable {
public BaseException(String message) {
super(message);
}
}
@@ -0,0 +1,131 @@
import java.io.BufferedReader;
import Controllers.Controller;
import Exceptions.BaseException;
import Models.Expressions.ArithmeticExpression;
import Models.Expressions.ReadHeap;
import Models.Expressions.RelationalExpression;
import Models.Expressions.ValueExpression;
import Models.Expressions.VariableExpression;
import Models.Program.GenericDictionary;
import Models.Program.GenericQueue;
import Models.Program.GenericStack;
import Models.Program.Heap;
import Models.Program.ProgramState;
import Models.Statements.AssignmentStatement;
import Models.Statements.CloseReadFileStatement;
import Models.Statements.CompoundStatement;
import Models.Statements.ForkStatement;
import Models.Statements.IStatement;
import Models.Statements.IfStatement;
import Models.Statements.NewStatement;
import Models.Statements.OpenReadFileStatement;
import Models.Statements.PrintStatement;
import Models.Statements.ReadFileStatement;
import Models.Statements.VariableDeclarationStatement;
import Models.Statements.WhileStatement;
import Models.Statements.WriteHeap;
import Models.Types.BooleanType;
import Models.Types.IntegerType;
import Models.Types.ReferenceType;
import Models.Types.StringType;
import Models.Values.BooleanValue;
import Models.Values.IValue;
import Models.Values.IntegerValue;
import Models.Values.StringValue;
import Repositories.IRepository;
import Repositories.Repository;
import Views.TextMenu;
import Views.Commands.ExitCommand;
import Views.Commands.RunExampleCommand;
public class Interpreter {
public static void main(String[] args) throws BaseException{
IStatement ex1= new CompoundStatement(new VariableDeclarationStatement("v", new IntegerType()), new CompoundStatement(new AssignmentStatement("v", new ValueExpression(new IntegerValue((2)))), new PrintStatement(new VariableExpression(("v")))));
ProgramState programState1 = new ProgramState(new GenericStack<IStatement>(), new GenericDictionary<String,IValue>(), new GenericQueue<IValue>(), new GenericDictionary<StringValue, BufferedReader>(), new Heap(),ex1);
IRepository repository1 = new Repository("log1.txt");
repository1.addProgramState(programState1);
Controller controller1 = new Controller(repository1, true);
IStatement ex2 = new CompoundStatement( new VariableDeclarationStatement("a",new IntegerType()),
new CompoundStatement(new VariableDeclarationStatement("b",new IntegerType()),
new CompoundStatement(new AssignmentStatement("a", new ArithmeticExpression('+',new ValueExpression(new IntegerValue(2)),new
ArithmeticExpression('*',new ValueExpression(new IntegerValue(3)), new ValueExpression(new IntegerValue(5))))),
new CompoundStatement(new AssignmentStatement("b",new ArithmeticExpression('+',new VariableExpression("a"), new ValueExpression(new
IntegerValue(1)))), new PrintStatement(new VariableExpression("b"))))));
ProgramState programState2 = new ProgramState(new GenericStack<IStatement>(), new GenericDictionary<String,IValue>(), new GenericQueue<IValue>(), new GenericDictionary<StringValue, BufferedReader>(), new Heap(),ex2);
IRepository repository2 = new Repository("log2.txt");
repository2.addProgramState(programState2);
Controller controller2 = new Controller(repository2, true);
IStatement ex3 = new CompoundStatement(new VariableDeclarationStatement("a",new BooleanType()),
new CompoundStatement(new VariableDeclarationStatement("v", new IntegerType()),
new CompoundStatement(new AssignmentStatement("a", new ValueExpression(new BooleanValue(true))),
new CompoundStatement(new IfStatement(new VariableExpression("a"),new AssignmentStatement("v",new ValueExpression(new
IntegerValue(2))), new AssignmentStatement("v", new ValueExpression(new IntegerValue(3)))), new PrintStatement(new
VariableExpression("v"))))));
ProgramState programState3 = new ProgramState(new GenericStack<IStatement>(), new GenericDictionary<String,IValue>(), new GenericQueue<IValue>(), new GenericDictionary<StringValue, BufferedReader>(), new Heap(),ex3);
IRepository repository3 = new Repository("log3.txt");
repository3.addProgramState(programState3);
Controller controller3 = new Controller(repository3, true);
IStatement ex4 = new CompoundStatement(new VariableDeclarationStatement("varf", new StringType()), new CompoundStatement(new AssignmentStatement("varf", new ValueExpression(new StringValue("test.in"))), new CompoundStatement(new OpenReadFileStatement(new VariableExpression("varf")), new CompoundStatement(new VariableDeclarationStatement("varc", new IntegerType()), new CompoundStatement(new ReadFileStatement(new VariableExpression("varf"), "varc"), new CompoundStatement(new PrintStatement(new VariableExpression("varc")), new CompoundStatement(new ReadFileStatement(new VariableExpression("varf"), "varc"), new CompoundStatement(new PrintStatement(new VariableExpression("varc")), new CloseReadFileStatement(new VariableExpression("varf"))))))))));
ProgramState programState4 = new ProgramState(new GenericStack<IStatement>(), new GenericDictionary<String,IValue>(), new GenericQueue<IValue>(), new GenericDictionary<StringValue, BufferedReader>(), new Heap(),ex4);
IRepository repository4 = new Repository("log4.txt");
repository4.addProgramState(programState4);
Controller controller4 = new Controller(repository4, true);
IStatement ex5 = new CompoundStatement(new IfStatement(new RelationalExpression(new ValueExpression(new IntegerValue(1)), new ValueExpression(new IntegerValue(2)), "<"), new PrintStatement(new ValueExpression(new IntegerValue(1))),new PrintStatement(new ValueExpression(new IntegerValue(2)))), new PrintStatement(new ValueExpression(new IntegerValue(3))));
ProgramState programState5 = new ProgramState(new GenericStack<IStatement>(), new GenericDictionary<String, IValue>(), new GenericQueue<IValue>(), new GenericDictionary<StringValue, BufferedReader>(), new Heap(),ex5);
IRepository repository5 = new Repository("log5.txt");
repository5.addProgramState(programState5);
Controller controller5 = new Controller(repository5, true);
IStatement ex6 = new CompoundStatement(new VariableDeclarationStatement("v", new ReferenceType(new IntegerType())), new CompoundStatement(new NewStatement("v", new ValueExpression(new IntegerValue(20))), new CompoundStatement(new VariableDeclarationStatement("a", new ReferenceType(new ReferenceType(new IntegerType()))), new CompoundStatement(new NewStatement("a", new VariableExpression("v")), new CompoundStatement(new NewStatement("v", new ValueExpression(new IntegerValue(30))), new PrintStatement(new ReadHeap(new ReadHeap(new VariableExpression("a")))))))));
ProgramState programState6 = new ProgramState(new GenericStack<IStatement>(), new GenericDictionary<String, IValue>(), new GenericQueue<IValue>(), new GenericDictionary<StringValue, BufferedReader>(), new Heap(),ex6);
IRepository repository6 = new Repository("log6.txt");
repository6.addProgramState(programState6);
Controller controller6 = new Controller(repository6, true);
IStatement ex7 = new CompoundStatement(new VariableDeclarationStatement("v", new ReferenceType(new IntegerType())), new CompoundStatement(new NewStatement("v", new ValueExpression(new IntegerValue(10))), new CompoundStatement(new NewStatement("v", new ValueExpression(new IntegerValue(20))), new PrintStatement(new VariableExpression("v")))));
ProgramState programState7 = new ProgramState(new GenericStack<IStatement>(), new GenericDictionary<String, IValue>(), new GenericQueue<IValue>(), new GenericDictionary<StringValue, BufferedReader>(), new Heap(),ex7);
IRepository repository7 = new Repository("log7.txt");
repository7.addProgramState(programState7);
Controller controller7 = new Controller(repository7, true);
IStatement ex8 = new CompoundStatement(new VariableDeclarationStatement("v", new IntegerType()), new CompoundStatement(new AssignmentStatement("v", new ValueExpression(new IntegerValue(4))), new CompoundStatement(new WhileStatement(new CompoundStatement(new PrintStatement(new VariableExpression("v")), new AssignmentStatement("v", new ArithmeticExpression('-', new VariableExpression("v"), new ValueExpression(new IntegerValue(1))))), new RelationalExpression(new VariableExpression("v"), new ValueExpression(new IntegerValue(0)), ">")), new PrintStatement(new VariableExpression("v")))));
ProgramState programState8 = new ProgramState(new GenericStack<IStatement>(), new GenericDictionary<String, IValue>(), new GenericQueue<IValue>(), new GenericDictionary<StringValue, BufferedReader>(), new Heap(),ex8);
IRepository repository8 = new Repository("log8.txt");
repository8.addProgramState(programState8);
Controller controller8 = new Controller(repository8, true);
IStatement ex9 = new CompoundStatement(new VariableDeclarationStatement("v", new IntegerType()), new CompoundStatement(new VariableDeclarationStatement("a", new ReferenceType(new IntegerType())), new CompoundStatement(new AssignmentStatement("v", new ValueExpression(new IntegerValue(10))), new CompoundStatement(new NewStatement("a", new ValueExpression(new IntegerValue(22))), new CompoundStatement(new ForkStatement(new CompoundStatement(new WriteHeap("a", new ValueExpression(new IntegerValue(30))), new CompoundStatement(new AssignmentStatement("v", new ValueExpression(new IntegerValue(32))), new CompoundStatement(new PrintStatement(new VariableExpression("v")), new PrintStatement(new ReadHeap(new VariableExpression("a"))))))), new CompoundStatement(new PrintStatement(new VariableExpression("v")), new PrintStatement(new ReadHeap(new VariableExpression("a")))))))));
ProgramState programState9 = new ProgramState(new GenericStack<IStatement>(), new GenericDictionary<String, IValue>(), new GenericQueue<IValue>(), new GenericDictionary<StringValue, BufferedReader>(), new Heap(),ex9);
IRepository repository9 = new Repository("log9.txt");
repository9.addProgramState(programState9);
Controller controller9 = new Controller(repository9, true);
IStatement badTypes = new CompoundStatement(new VariableDeclarationStatement("v", new IntegerType()), new AssignmentStatement("v", new ValueExpression(new BooleanValue(true))));
ProgramState badProgramState = new ProgramState(new GenericStack<IStatement>(), new GenericDictionary<String, IValue>(), new GenericQueue<IValue>(), new GenericDictionary<StringValue, BufferedReader>(), new Heap(),badTypes);
try{
IRepository badRepository = new Repository("logBad.txt");
badRepository.addProgramState(badProgramState);
}
catch(BaseException exception){
System.out.println(exception.getMessage());
}
TextMenu menu = new TextMenu();
menu.addCommand(new RunExampleCommand("1", "Run example 1", controller1));
menu.addCommand(new RunExampleCommand("2", "Run example 2", controller2));
menu.addCommand(new RunExampleCommand("3", "Run example 3", controller3));
menu.addCommand(new RunExampleCommand("4", "Run example 4", controller4));
menu.addCommand(new RunExampleCommand("5", "Run example 5", controller5));
menu.addCommand(new RunExampleCommand("6", "Run example 6", controller6));
menu.addCommand(new RunExampleCommand("7", "Run example 7", controller7));
menu.addCommand(new RunExampleCommand("8", "Run example 8", controller8));
menu.addCommand(new RunExampleCommand("9", "Run example 9", controller9));
menu.addCommand(new ExitCommand("e", "Exit"));
menu.show();
}
}
@@ -0,0 +1,77 @@
package Models.Expressions;
import Exceptions.BaseException;
import Models.Program.IDictionary;
import Models.Program.IHeap;
import Models.Types.IType;
import Models.Types.IntegerType;
import Models.Values.IntegerValue;
import Models.Values.IValue;
public class ArithmeticExpression implements IExpression {
private IExpression left;
private IExpression right;
private char operator;
public ArithmeticExpression(char operator,IExpression left, IExpression right) {
this.left = left;
this.right = right;
this.operator = operator;
}
public IValue evaluate(IDictionary<String, IValue> table, IHeap heap) throws BaseException {
IValue leftValue = left.evaluate(table, heap);
IValue rightValue = right.evaluate(table, heap);
if (leftValue.getType().equals(new IntegerType())) {
int leftInt = ((IntegerValue)leftValue).getValue();
if (rightValue.getType().equals(new IntegerType())) {
int rightInt = ((IntegerValue)rightValue).getValue();
switch (operator) {
case '+':
return new IntegerValue(leftInt + rightInt);
case '-':
return new IntegerValue(leftInt - rightInt);
case '*':
return new IntegerValue(leftInt * rightInt);
case '/':
if (rightInt == 0) {
throw new BaseException("Division by zero!");
}
return new IntegerValue(leftInt / rightInt);
default:
throw new BaseException("Invalid operator!");
}
} else {
throw new BaseException("Second operand is not an integer!");
}
} else {
throw new BaseException("First operand is not an integer!");
}
}
public IExpression copy() {
return new ArithmeticExpression(operator, left.copy(), right.copy());
}
public String toString() {
return left.toString() + " " + operator + " " + right.toString();
}
public IType typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
IType type1, type2;
type1 = left.typeCheck(typeTable);
type2 = right.typeCheck(typeTable);
if (type1.equals(new IntegerType())) {
if (type2.equals(new IntegerType())) {
return new IntegerType();
} else {
throw new BaseException("Second operand is not an integer!");
}
} else {
throw new BaseException("First operand is not an integer!");
}
}
}
@@ -0,0 +1,13 @@
package Models.Expressions;
import Exceptions.BaseException;
import Models.Program.IDictionary;
import Models.Program.IHeap;
import Models.Types.IType;
import Models.Values.IValue;
public interface IExpression {
public IValue evaluate(IDictionary<String, IValue> table, IHeap heap) throws BaseException;
public IType typeCheck(IDictionary<String, IType> typeTable) throws BaseException;
public IExpression copy();
}
@@ -0,0 +1,70 @@
package Models.Expressions;
import Exceptions.BaseException;
import Models.Program.IDictionary;
import Models.Program.IHeap;
import Models.Types.BooleanType;
import Models.Types.IType;
import Models.Values.BooleanValue;
import Models.Values.IValue;
public class LogicExpression implements IExpression {
private IExpression left;
private IExpression right;
private String operator;
public LogicExpression(IExpression left, IExpression right, String operator) {
this.left = left;
this.right = right;
this.operator = operator;
}
public IValue evaluate(IDictionary<String, IValue> table, IHeap heap) throws BaseException {
IValue leftValue = left.evaluate(table, heap);
IValue rightValue = right.evaluate(table, heap);
if (leftValue.getType().equals(new BooleanType())) {
boolean leftBool = ((BooleanValue)leftValue).getValue();
if (rightValue.getType().equals(new BooleanType())) {
boolean rightBool = ((BooleanValue)rightValue).getValue();
switch (operator) {
case "&&":
return new BooleanValue(leftBool && rightBool);
case "||":
return new BooleanValue(leftBool || rightBool);
default:
throw new BaseException("Invalid operator!");
}
} else {
throw new BaseException("Second operand is not a boolean!");
}
} else {
throw new BaseException("First operand is not a boolean!");
}
}
public IExpression copy() {
return new LogicExpression(left.copy(), right.copy(), operator);
}
public String toString() {
return left.toString() + " " + operator + " " + right.toString();
}
public IType typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
IType leftType, rightType;
leftType = left.typeCheck(typeTable);
rightType = right.typeCheck(typeTable);
if (leftType.equals(new BooleanType())) {
if (rightType.equals(new BooleanType())) {
return new BooleanType();
} else {
throw new BaseException("Second operand is not a boolean!");
}
} else {
throw new BaseException("First operand is not a boolean!");
}
}
}
@@ -0,0 +1,41 @@
package Models.Expressions;
import Exceptions.BaseException;
import Models.Program.IDictionary;
import Models.Program.IHeap;
import Models.Types.IType;
import Models.Types.ReferenceType;
import Models.Values.IValue;
import Models.Values.ReferenceValue;
public class ReadHeap implements IExpression {
private IExpression expression;
public ReadHeap(IExpression expression) {
this.expression = expression;
}
public IValue evaluate(IDictionary<String, IValue> table, IHeap heap) throws BaseException {
IValue value = this.expression.evaluate(table, heap);
if(!(value instanceof ReferenceValue)) {
throw new BaseException("Expression is not a reference value");
}
int address = ((ReferenceValue)value).getAddress();
if(!heap.contains(address)) {
throw new BaseException("Address " + address + " is not in the heap");
}
return heap.get(address);
}
public IExpression copy() {
return new ReadHeap(this.expression.copy());
}
public IType typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
IType type = this.expression.typeCheck(typeTable);
if(!(type instanceof ReferenceType)) {
throw new BaseException("Expression is not a reference value");
}
return ((ReferenceType)type).getInnerType();
}
}
@@ -0,0 +1,71 @@
package Models.Expressions;
import Exceptions.BaseException;
import Models.Program.IDictionary;
import Models.Program.IHeap;
import Models.Types.BooleanType;
import Models.Types.IType;
import Models.Types.IntegerType;
import Models.Values.BooleanValue;
import Models.Values.IValue;
import Models.Values.IntegerValue;
public class RelationalExpression implements IExpression {
private IExpression leftExpression;
private IExpression rightExpression;
private String operator;
public RelationalExpression(IExpression leftExpression, IExpression rightExpression, String operator) {
this.leftExpression = leftExpression;
this.rightExpression = rightExpression;
this.operator = operator;
}
public IExpression copy() {
return new RelationalExpression(this.leftExpression.copy(), this.rightExpression.copy(), this.operator);
}
public String toString() {
return this.leftExpression.toString() + " " + this.operator + " " + this.rightExpression.toString();
}
public IValue evaluate(IDictionary<String, IValue> symbolTable, IHeap heap) throws BaseException {
var leftValue = this.leftExpression.evaluate(symbolTable, heap);
var rightValue = this.rightExpression.evaluate(symbolTable, heap);
if (leftValue.getType().equals(new IntegerType()) && rightValue.getType().equals(new IntegerType())) {
var leftIntegerValue = (IntegerValue) leftValue;
var rightIntegerValue = (IntegerValue) rightValue;
var leftInteger = leftIntegerValue.getValue();
var rightInteger = rightIntegerValue.getValue();
switch (this.operator) {
case "<":
return new BooleanValue(leftInteger < rightInteger);
case "<=":
return new BooleanValue(leftInteger <= rightInteger);
case "==":
return new BooleanValue(leftInteger == rightInteger);
case "!=":
return new BooleanValue(leftInteger != rightInteger);
case ">":
return new BooleanValue(leftInteger > rightInteger);
case ">=":
return new BooleanValue(leftInteger >= rightInteger);
default:
throw new BaseException("RelationalExpression: Invalid operator");
}
}
throw new BaseException("RelationalExpression: Operands are not of type IntegerType");
}
public IType typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
var leftType = this.leftExpression.typeCheck(typeTable);
var rightType = this.rightExpression.typeCheck(typeTable);
if (leftType.equals(new IntegerType())) {
if (rightType.equals(new IntegerType())) {
return new BooleanType();
}
throw new BaseException("RelationalExpression: Right operand is not of type IntegerType");
}
throw new BaseException("RelationalExpression: Left operand is not of type IntegerType");
}
}
@@ -0,0 +1,31 @@
package Models.Expressions;
import Models.Values.IValue;
import Exceptions.BaseException;
import Models.Program.IDictionary;
import Models.Program.IHeap;
import Models.Types.IType;
public class ValueExpression implements IExpression {
private IValue value;
public ValueExpression(IValue value) {
this.value = value;
}
public IValue evaluate(IDictionary<String, IValue> table, IHeap heap) throws BaseException {
return value;
}
public IExpression copy() {
return new ValueExpression(value);
}
public String toString() {
return value.toString();
}
public IType typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
return value.getType();
}
}
@@ -0,0 +1,31 @@
package Models.Expressions;
import Exceptions.BaseException;
import Models.Program.IDictionary;
import Models.Program.IHeap;
import Models.Types.IType;
import Models.Values.IValue;
public class VariableExpression implements IExpression {
private String name;
public VariableExpression(String name) {
this.name = name;
}
public IValue evaluate(IDictionary<String, IValue> table, IHeap heap) throws BaseException {
return table.get(name);
}
public IExpression copy() {
return new VariableExpression(name);
}
public String toString() {
return name;
}
public IType typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
return typeTable.get(name);
}
}
@@ -0,0 +1,72 @@
package Models.Program;
import Exceptions.BaseException;
import java.util.Collection;
import java.util.Hashtable;
public class GenericDictionary<K, V> implements IDictionary<K, V> {
private Hashtable<K, V> dictionary;
public GenericDictionary() {
dictionary = new Hashtable<K, V>();
}
public void add(K key, V value) throws BaseException {
if (dictionary.containsKey(key)) {
throw new BaseException("Key already exists in dictionary.");
}
dictionary.put(key, value);
}
public void update(K key, V value) throws BaseException {
if (!dictionary.containsKey(key)) {
throw new BaseException("Key does not exist in dictionary.");
}
dictionary.put(key, value);
}
public void remove(K key) throws BaseException {
if (!dictionary.containsKey(key)) {
throw new BaseException("Key does not exist in dictionary.");
}
dictionary.remove(key);
}
public V get(K key) throws BaseException {
if (!dictionary.containsKey(key)) {
throw new BaseException("Key does not exist in dictionary.");
}
return dictionary.get(key);
}
public boolean contains(K key) {
return dictionary.containsKey(key);
}
public String toString() {
var sb = new StringBuilder();
for (var key : dictionary.keySet()) {
sb.append(key);
sb.append(" --> ");
sb.append(dictionary.get(key));
sb.append("\n");
}
return sb.toString();
}
public Collection<V> getContent() {
return dictionary.values();
}
public IDictionary<K, V> copy() {
var newDictionary = new GenericDictionary<K, V>();
for (var key : dictionary.keySet()) {
newDictionary.dictionary.put(key, dictionary.get(key));
}
return newDictionary;
}
}
@@ -0,0 +1,30 @@
package Models.Program;
import java.util.Queue;
import java.util.LinkedList;
public class GenericQueue<T> implements IQueue<T> {
private Queue<T> queue;
public GenericQueue() {
this.queue = new LinkedList<T>();
}
public T dequeue() {
return queue.poll();
}
public void enqueue(T value) {
queue.add(value);
}
public String toString() {
var sb = new StringBuilder();
for (var item : queue) {
sb.append(item);
sb.append("\n");
}
return sb.toString();
}
}
@@ -0,0 +1,34 @@
package Models.Program;
import java.util.ArrayDeque;
import java.util.Deque;
public class GenericStack<T> implements IStack<T> {
private Deque<T> stack;
public GenericStack() {
stack = new ArrayDeque<T>();
}
public T pop() {
return stack.pop();
}
public void push(T value) {
stack.push(value);
}
public boolean isEmpty() {
return stack.isEmpty();
}
public String toString() {
var sb = new StringBuilder();
for (var item : stack) {
sb.append(item);
sb.append("\n");
}
return sb.toString();
}
}
@@ -0,0 +1,74 @@
package Models.Program;
import java.util.Hashtable;
import Exceptions.BaseException;
import Models.Values.IValue;
public class Heap implements IHeap{
private Integer freeAddress;
private Hashtable<Integer, IValue> heap;
public Heap() {
this.freeAddress = 1;
this.heap = new Hashtable<Integer, IValue>();
}
public Integer getFreeAddress() {
return this.freeAddress;
}
public Boolean contains(Integer address) {
return this.heap.containsKey(address);
}
public Integer add(IValue value) {
this.heap.put(this.freeAddress, value);
this.freeAddress += 1;
return this.freeAddress - 1;
}
public void update(Integer address, IValue value) throws BaseException {
if (!this.heap.containsKey(address)) {
throw new BaseException("Address does not exist in heap.");
}
this.heap.put(address, value);
}
public IValue get(Integer address) throws BaseException {
if (!this.heap.containsKey(address)) {
throw new BaseException("Address does not exist in heap.");
}
return this.heap.get(address);
}
public void remove(Integer address) throws BaseException {
if (!this.heap.containsKey(address)) {
throw new BaseException("Address does not exist in heap.");
}
this.heap.remove(address);
}
public String toString() {
var sb = new StringBuilder();
for (var key : this.heap.keySet()) {
sb.append(key);
sb.append(" --> ");
sb.append(this.heap.get(key));
sb.append("\n");
}
return sb.toString();
}
public Hashtable<Integer, IValue> getContent() {
return this.heap;
}
public void setContent(Hashtable<Integer, IValue> content) {
this.heap = content;
}
}
@@ -0,0 +1,15 @@
package Models.Program;
import java.util.Collection;
import Exceptions.BaseException;
public interface IDictionary<K, V> {
public void add(K key, V value) throws BaseException;
public void update(K key, V value) throws BaseException;
public void remove(K key) throws BaseException;
public V get(K key) throws BaseException;
public boolean contains(K key);
public Collection<V> getContent();
public IDictionary<K, V> copy();
}
@@ -0,0 +1,17 @@
package Models.Program;
import java.util.Hashtable;
import Exceptions.BaseException;
import Models.Values.IValue;
public interface IHeap {
public Integer getFreeAddress();
public Integer add(IValue value);
public void update(Integer address, IValue value) throws BaseException;
public IValue get(Integer address) throws BaseException;
public void remove(Integer address) throws BaseException;
public Boolean contains(Integer address);
public Hashtable<Integer, IValue> getContent();
public void setContent(Hashtable<Integer, IValue> content);
}
@@ -0,0 +1,8 @@
package Models.Program;
import Exceptions.BaseException;
public interface IQueue<T> {
public T dequeue() throws BaseException;
public void enqueue(T value);
}
@@ -0,0 +1,7 @@
package Models.Program;
public interface IStack<T> {
public T pop();
public void push(T value);
public boolean isEmpty();
}
@@ -0,0 +1,92 @@
package Models.Program;
import java.io.BufferedReader;
import java.util.Set;
import Exceptions.BaseException;
import Models.Statements.IStatement;
import Models.Types.IType;
import Models.Values.IValue;
import Models.Values.StringValue;;
public class ProgramState{
//region Fields
private IStack<IStatement> stack;
private IDictionary<String, IValue> symbolTable;
private IQueue<IValue> output;
private IDictionary<StringValue, BufferedReader> fileTable;
private IStatement originalProgram;
private IHeap heap;
private Integer id;
private static Set<Integer> ids = new java.util.HashSet<>();
//endregion
//region Exposed Methods
public ProgramState(IStack<IStatement> stack, IDictionary<String, IValue> symbolTable, IQueue<IValue> output, IDictionary<StringValue, BufferedReader> fileTable, IHeap heap,IStatement program) throws BaseException{
this.stack = stack;
this.symbolTable = symbolTable;
this.output = output;
this.fileTable = fileTable;
this.originalProgram = program.copy();
this.stack.push(program);
this.heap = heap;
this.id = getNewId();
}
private static Integer getNewId(){
Integer newId = 1;
synchronized (ids){
while(ids.contains(newId)){
newId++;
}
ids.add(newId);
}
return newId;
}
public IStack<IStatement> getStack(){
return this.stack;
}
public IDictionary<String, IValue> getSymbolTable(){
return this.symbolTable;
}
public IQueue<IValue> getOutput(){
return this.output;
}
public IDictionary<StringValue, BufferedReader> getFileTable(){
return this.fileTable;
}
public IStatement getOriginalProgram(){
return this.originalProgram;
}
public IHeap getHeap(){
return this.heap;
}
public boolean isNotCompleted(){
return !this.stack.isEmpty();
}
public ProgramState oneStep() throws BaseException{
IStack<IStatement> stack = this.getStack();
if (stack.isEmpty()) {
throw new RuntimeException("Execution stack is empty!");
}
IStatement currentStatement = stack.pop();
return currentStatement.execute(this);
}
public String toString(){
return "Id: " + id + "\n" + "Stack:\n" + this.stack.toString() + "\nSymbol Table:\n" + this.symbolTable.toString() + "\nOutput:\n" + this.output.toString() + "\nFile Table:\n" + this.fileTable.toString() + "\n" + "Heap:" + "\n" + this.heap.toString() + "\n";
}
public void typeCheck() throws BaseException{
this.originalProgram.typeCheck(new GenericDictionary<String, IType>());
}
//#endregion
}
@@ -0,0 +1,54 @@
package Models.Statements;
import Exceptions.BaseException;
import Models.Expressions.IExpression;
import Models.Program.IDictionary;
import Models.Program.IHeap;
import Models.Program.ProgramState;
import Models.Types.IType;
import Models.Values.IValue;
public class AssignmentStatement implements IStatement {
private String variableName;
private IExpression expression;
public AssignmentStatement(String variableName, IExpression expression) {
this.variableName = variableName;
this.expression = expression;
}
public String toString() {
return variableName + " = " + expression.toString();
}
public IStatement copy() {
return new AssignmentStatement(variableName, expression.copy());
}
public ProgramState execute(ProgramState state) throws BaseException {
IDictionary<String, IValue> symbolTable = state.getSymbolTable();
IHeap heap = state.getHeap();
if(symbolTable.contains(variableName)) {
IValue value = expression.evaluate(symbolTable, heap);
IType variableType = (symbolTable.get(variableName)).getType();
if(value.getType().equals(variableType)) {
symbolTable.update(variableName, value);
} else {
throw new BaseException("Declared type of variable " + variableName + " and type of the assigned expression do not match!");
}
} else {
throw new BaseException("Variable " + variableName + " is not defined!");
}
return null;
}
public IDictionary<String, IType> typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
IType variableType = typeTable.get(variableName);
IType expressionType = expression.typeCheck(typeTable);
if(variableType.equals(expressionType)) {
return typeTable;
} else {
throw new BaseException("Declared type of variable " + variableName + " and type of the assigned expression do not match!");
}
}
}
@@ -0,0 +1,52 @@
package Models.Statements;
import Exceptions.BaseException;
import Models.Expressions.IExpression;
import Models.Program.IDictionary;
import Models.Program.ProgramState;
import Models.Types.IType;
import Models.Types.StringType;
import Models.Values.StringValue;
public class CloseReadFileStatement implements IStatement{
private IExpression expression;
public CloseReadFileStatement(IExpression expression){
this.expression = expression;
}
public IStatement copy(){
return new CloseReadFileStatement(this.expression.copy());
}
public String toString(){
return "closeRFile(" + this.expression.toString() + ")";
}
public ProgramState execute(ProgramState programState) throws BaseException{
var value = this.expression.evaluate(programState.getSymbolTable(), programState.getHeap());
if(!value.getType().equals(new StringType())){
throw new BaseException("CloseReadFileStatement: Expression is not of type StringType");
}
if(!programState.getFileTable().contains((StringValue)value)){
throw new BaseException("CloseReadFileStatement: File is not open");
}
var bufferedReader = programState.getFileTable().get((StringValue)value);
try{
bufferedReader.close();
}
catch(Exception exception){
throw new BaseException("CloseReadFileStatement: File could not be closed");
}
programState.getFileTable().remove((StringValue)value);
return null;
}
public IDictionary<String, IType> typeCheck(IDictionary<String, IType> typeTable) throws BaseException{
var expressionType = this.expression.typeCheck(typeTable);
if(!expressionType.equals(new StringType())){
throw new BaseException("CloseReadFileStatement: Expression is not of type StringType");
}
return typeTable;
}
}
@@ -0,0 +1,40 @@
package Models.Statements;
import Exceptions.BaseException;
import Models.Program.IDictionary;
import Models.Program.IStack;
import Models.Program.ProgramState;
import Models.Types.IType;
public class CompoundStatement implements IStatement {
//region Fields
private IStatement first;
private IStatement second;
//endregion
//region Exposed Methods
public CompoundStatement(IStatement first, IStatement second){
this.first = first;
this.second = second;
}
public String toString(){
return "(" + first.toString() + ";" + second.toString() + ")";
}
public IStatement copy(){
return new CompoundStatement(first.copy(), second.copy());
}
public ProgramState execute(ProgramState state){
IStack<IStatement> stack = state.getStack();
stack.push(second);
stack.push(first);
return null;
}
public IDictionary<String, IType> typeCheck(IDictionary<String, IType> typeTable) throws BaseException{
return second.typeCheck(first.typeCheck(typeTable));
}
//endregion
}
@@ -0,0 +1,33 @@
package Models.Statements;
import Exceptions.BaseException;
import Models.Program.GenericStack;
import Models.Program.IDictionary;
import Models.Program.ProgramState;
import Models.Types.IType;
public class ForkStatement implements IStatement {
private IStatement statement;
public ForkStatement(IStatement statement) {
this.statement = statement;
}
public ProgramState execute(ProgramState state) throws BaseException {
ProgramState forkedProgramState = new ProgramState(new GenericStack<IStatement>(), state.getSymbolTable().copy(), state.getOutput(), state.getFileTable(), state.getHeap(), this.statement);
return forkedProgramState;
}
public IStatement copy() {
return new ForkStatement(this.statement.copy());
}
public String toString() {
return "fork(" + this.statement.toString() + ")";
}
public IDictionary<String, IType> typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
this.statement.typeCheck(typeTable.copy());
return typeTable;
}
}
@@ -0,0 +1,12 @@
package Models.Statements;
import Models.Program.IDictionary;
import Models.Program.ProgramState;
import Models.Types.IType;
import Exceptions.BaseException;
public interface IStatement{
public ProgramState execute(ProgramState state) throws BaseException;
public IStatement copy();
public IDictionary<String, IType> typeCheck(IDictionary<String, IType> typeTable) throws BaseException;
}
@@ -0,0 +1,60 @@
package Models.Statements;
import Exceptions.BaseException;
import Models.Expressions.IExpression;
import Models.Program.IDictionary;
import Models.Program.IHeap;
import Models.Program.ProgramState;
import Models.Types.BooleanType;
import Models.Types.IType;
import Models.Values.BooleanValue;
import Models.Values.IValue;
public class IfStatement implements IStatement {
private IStatement thenStatement;
private IStatement elseStatement;
private IExpression condition;
public IfStatement(IExpression condition, IStatement thenStatement, IStatement elseStatement) {
this.condition = condition;
this.thenStatement = thenStatement;
this.elseStatement = elseStatement;
}
public String toString() {
return "(if(" + condition.toString() + ") then(" + thenStatement.toString() + ") else(" + elseStatement.toString() + "))";
}
public IStatement copy() {
return new IfStatement(condition.copy(), thenStatement.copy(), elseStatement.copy());
}
public ProgramState execute(ProgramState state) throws BaseException {
IDictionary<String, IValue> symbolTable = state.getSymbolTable();
IHeap heap = state.getHeap();
IValue conditionValue = condition.evaluate(symbolTable, heap);
if (conditionValue.getType().equals(new BooleanType())) {
boolean conditionBool = ((BooleanValue)conditionValue).getValue();
if (conditionBool) {
thenStatement.execute(state);
} else {
elseStatement.execute(state);
}
} else {
throw new BaseException("Condition is not a boolean!");
}
return null;
}
public IDictionary<String, IType> typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
IType conditionType = condition.typeCheck(typeTable);
if (conditionType.equals(new BooleanType())) {
thenStatement.typeCheck(typeTable.copy());
elseStatement.typeCheck(typeTable.copy());
return typeTable;
} else {
throw new BaseException("Condition is not a boolean!");
}
}
}
@@ -0,0 +1,52 @@
package Models.Statements;
import Exceptions.BaseException;
import Models.Expressions.IExpression;
import Models.Program.IDictionary;
import Models.Program.ProgramState;
import Models.Types.IType;
import Models.Types.ReferenceType;
import Models.Values.ReferenceValue;
public class NewStatement implements IStatement {
private String variableName;
private IExpression expression;
public NewStatement(String variableName, IExpression expression) {
this.variableName = variableName;
this.expression = expression;
}
public IStatement copy() {
return new NewStatement(this.variableName, this.expression.copy());
}
public String toString() {
return "new(" + this.variableName + ", " + this.expression.toString() + ")";
}
public ProgramState execute(ProgramState programState) throws BaseException {
var symbolTable = programState.getSymbolTable();
var heap = programState.getHeap();
if (!symbolTable.contains(this.variableName)) {
throw new BaseException("NewStatement: Variable is not defined");
}
var value = symbolTable.get(this.variableName);
var expressionValue = this.expression.evaluate(symbolTable, heap);
if (!value.getType().equals(new ReferenceType(expressionValue.getType()))) {
throw new BaseException("NewStatement: Variable is not of type ReferenceType");
}
var address = heap.add(expressionValue);
symbolTable.update(this.variableName, new ReferenceValue(address, expressionValue.getType()));
return null;
}
public IDictionary<String, IType> typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
var variableType = typeTable.get(this.variableName);
var expressionType = this.expression.typeCheck(typeTable);
if (!variableType.equals(new ReferenceType(expressionType))) {
throw new BaseException("NewStatement: Right hand side and Left hand side have different types");
}
return typeTable;
}
}
@@ -0,0 +1,23 @@
package Models.Statements;
import Models.Program.IDictionary;
import Models.Program.ProgramState;
import Models.Types.IType;
public class NopStatement implements IStatement {
public String toString() {
return "";
}
public IStatement copy() {
return new NopStatement();
}
public ProgramState execute(ProgramState state) {
return null;
}
public IDictionary<String, IType> typeCheck(IDictionary<String, IType> typeTable) {
return typeTable;
}
}
@@ -0,0 +1,57 @@
package Models.Statements;
import java.io.BufferedReader;
import java.io.FileReader;
import Exceptions.BaseException;
import Models.Expressions.IExpression;
import Models.Program.IDictionary;
import Models.Program.ProgramState;
import Models.Types.IType;
import Models.Types.StringType;
import Models.Values.StringValue;
public class OpenReadFileStatement implements IStatement {
private IExpression expression;
public OpenReadFileStatement(IExpression expression){
this.expression = expression;
}
public ProgramState execute(ProgramState programState) throws BaseException{
var value = this.expression.evaluate(programState.getSymbolTable(), programState.getHeap());
if(!value.getType().equals(new StringType())){
throw new BaseException("OpenReadFileStatement: Expression is not of type StringType");
}
var stringValue = (StringValue)value;
if(programState.getFileTable().contains(stringValue)){
throw new BaseException("OpenReadFileStatement: File is already open");
}
BufferedReader bufferedReader;
try{
bufferedReader = new BufferedReader(new FileReader(stringValue.getValue()));
}
catch(Exception exception){
throw new BaseException("OpenReadFileStatement: File does not exist");
}
programState.getFileTable().add(stringValue, bufferedReader);
return null;
}
public IStatement copy(){
return new OpenReadFileStatement(this.expression.copy());
}
public String toString(){
return "openRFile(" + this.expression.toString() + ")";
}
public IDictionary<String, IType> typeCheck(IDictionary<String, IType> typeTable) throws BaseException{
var expressionType = this.expression.typeCheck(typeTable);
if(!expressionType.equals(new StringType())){
throw new BaseException("OpenReadFileStatement: Expression is not of type StringType");
}
return typeTable;
}
}
@@ -0,0 +1,39 @@
package Models.Statements;
import Exceptions.BaseException;
import Models.Expressions.IExpression;
import Models.Program.IDictionary;
import Models.Program.IQueue;
import Models.Program.ProgramState;
import Models.Types.IType;
import Models.Values.IValue;
public class PrintStatement implements IStatement {
//region Fields
private IExpression expression;
//endregion
//region Exposed Methods
public PrintStatement(IExpression expression){
this.expression = expression;
}
public String toString(){
return "print(" + expression.toString() + ")";
}
public IStatement copy(){
return new PrintStatement(expression.copy());
}
public ProgramState execute(ProgramState state) throws BaseException{
IQueue<IValue> output = state.getOutput();
output.enqueue(expression.evaluate(state.getSymbolTable(), state.getHeap() ));
return null;
}
public IDictionary<String, IType> typeCheck(IDictionary<String, IType> typeTable) throws BaseException{
expression.typeCheck(typeTable);
return typeTable;
}
//endregion
}
@@ -0,0 +1,74 @@
package Models.Statements;
import Exceptions.BaseException;
import Models.Expressions.IExpression;
import Models.Program.IDictionary;
import Models.Program.ProgramState;
import Models.Types.IType;
import Models.Types.IntegerType;
import Models.Types.StringType;
import Models.Values.IntegerValue;
import Models.Values.StringValue;
public class ReadFileStatement implements IStatement{
private IExpression expression;
private String variableName;
public ReadFileStatement(IExpression expression, String variableName){
this.expression = expression;
this.variableName = variableName;
}
public IStatement copy(){
return new ReadFileStatement(this.expression.copy(), this.variableName);
}
public String toString(){
return "readFile(" + this.expression.toString() + ", " + this.variableName + ")";
}
public ProgramState execute(ProgramState programState) throws BaseException{
var symbolTable = programState.getSymbolTable();
var fileTable = programState.getFileTable();
var heap = programState.getHeap();
if(!symbolTable.contains(this.variableName)){
throw new BaseException("ReadFileStatement: Variable is not defined");
}
var value = symbolTable.get(this.variableName);
if(!value.getType().equals(new IntegerType())){
throw new BaseException("ReadFileStatement: Variable is not of type IntegerType");
}
var expressionValue = this.expression.evaluate(symbolTable, heap);
if(!expressionValue.getType().equals(new StringType())){
throw new BaseException("ReadFileStatement: Expression is not of type StringType");
}
if(!fileTable.contains((StringValue)expressionValue)){
throw new BaseException("ReadFileStatement: File is not open");
}
var bufferedReader = fileTable.get((StringValue)expressionValue);
try{
var line = bufferedReader.readLine();
if(line == null){
line = "0";
}
symbolTable.update(this.variableName, new IntegerValue(Integer.parseInt(line)));
}
catch(Exception exception){
throw new BaseException("ReadFileStatement: File is empty");
}
return null;
}
public IDictionary<String, IType> typeCheck(IDictionary<String, IType> typeTable) throws BaseException{
var expressionType = this.expression.typeCheck(typeTable);
if(!expressionType.equals(new StringType())){
throw new BaseException("ReadFileStatement: Expression is not of type StringType");
}
var variableType = typeTable.get(this.variableName);
if(!variableType.equals(new IntegerType())){
throw new BaseException("ReadFileStatement: Variable is not of type IntegerType");
}
return typeTable;
}
}
@@ -0,0 +1,41 @@
package Models.Statements;
import Exceptions.BaseException;
import Models.Program.IDictionary;
import Models.Program.ProgramState;
import Models.Types.IType;
import Models.Values.IValue;
public class VariableDeclarationStatement implements IStatement {
private String variableName;
private IType variableType;
public VariableDeclarationStatement(String variableName, IType variableType) {
this.variableName = variableName;
this.variableType = variableType;
}
public String toString() {
return variableType.toString() + " " + variableName;
}
public IStatement copy() {
return new VariableDeclarationStatement(variableName, variableType);
}
public ProgramState execute(ProgramState state) throws BaseException {
IDictionary<String, IValue> symbolTable = state.getSymbolTable();
if(!symbolTable.contains(variableName)) {
symbolTable.add(variableName, variableType.defaultValue());
} else {
throw new BaseException("Variable " + variableName + " is already defined!");
}
return null;
}
public IDictionary<String, IType> typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
typeTable.add(variableName, variableType);
return typeTable;
}
}
@@ -0,0 +1,58 @@
package Models.Statements;
import Exceptions.BaseException;
import Models.Expressions.IExpression;
import Models.Program.IDictionary;
import Models.Program.IHeap;
import Models.Program.IStack;
import Models.Program.ProgramState;
import Models.Types.BooleanType;
import Models.Types.IType;
import Models.Values.IValue;
import Models.Values.BooleanValue;
public class WhileStatement implements IStatement {
private IStatement statement;
private IExpression expression;
public WhileStatement(IStatement statement, IExpression expression) {
this.statement = statement;
this.expression = expression;
}
public ProgramState execute(ProgramState state) throws BaseException {
IStack<IStatement> stack = state.getStack();
IHeap heap = state.getHeap();
IDictionary<String, IValue> symbolTable = state.getSymbolTable();
IValue condition = expression.evaluate(symbolTable, heap);
if (!condition.getType().equals(new BooleanType())) {
throw new BaseException("Condition is not a boolean.");
}
if (((BooleanValue) condition).getValue()) {
stack.push(this);
stack.push(statement);
}
return null;
}
public String toString() {
return "while(" + expression.toString() + ") {" + statement.toString() + "}";
}
public IStatement copy() {
return new WhileStatement(statement.copy(), expression.copy());
}
public IDictionary<String, IType> typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
IType expressionType = expression.typeCheck(typeTable);
if (expressionType.equals(new BooleanType())) {
statement.typeCheck(typeTable.copy());
return typeTable;
} else {
throw new BaseException("Condition is not a boolean!");
}
}
}
@@ -0,0 +1,58 @@
package Models.Statements;
import Exceptions.BaseException;
import Models.Expressions.IExpression;
import Models.Program.IDictionary;
import Models.Program.ProgramState;
import Models.Types.IType;
import Models.Types.ReferenceType;
import Models.Values.ReferenceValue;
public class WriteHeap implements IStatement {
private String variableName;
private IExpression expression;
public WriteHeap(String variableName, IExpression expression) {
this.variableName = variableName;
this.expression = expression;
}
public ProgramState execute(ProgramState state) throws BaseException {
var symbolTable = state.getSymbolTable();
var heap = state.getHeap();
if(!symbolTable.contains(this.variableName)) {
throw new BaseException("Variable " + this.variableName + " is not defined");
}
if(!(symbolTable.get(this.variableName) instanceof ReferenceValue)) {
throw new BaseException("Variable " + this.variableName + " is not a reference value");
}
int address = ((ReferenceValue)symbolTable.get(this.variableName)).getAddress();
if(!heap.contains(address)) {
throw new BaseException("Address " + address + " is not in the heap");
}
var heapValue = heap.get(address);
var expressionValue = this.expression.evaluate(symbolTable, heap);
if(!heapValue.getType().equals(expressionValue.getType())) {
throw new BaseException("Types do not match");
}
heap.update(address, expressionValue);
return null;
}
public IStatement copy() {
return new WriteHeap(this.variableName, this.expression.copy());
}
public String toString() {
return "writeHeap(" + this.variableName + ", " + this.expression.toString() + ")";
}
public IDictionary<String, IType> typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
var variableType = typeTable.get(this.variableName);
var expressionType = this.expression.typeCheck(typeTable);
if(!variableType.equals(new ReferenceType(expressionType))) {
throw new BaseException("Types do not match");
}
return typeTable;
}
}
@@ -0,0 +1,19 @@
package Models.Types;
import Models.Values.BooleanValue;
import Models.Values.IValue;
public class BooleanType implements IType {
//#region Exposed Methods
public boolean equals(Object other){
return other instanceof BooleanType;
}
public String toString(){
return "boolean";
}
public IValue defaultValue(){
return new BooleanValue(false);
}
}
@@ -0,0 +1,7 @@
package Models.Types;
import Models.Values.IValue;
public interface IType {
public IValue defaultValue();
}
@@ -0,0 +1,19 @@
package Models.Types;
import Models.Values.IValue;
import Models.Values.IntegerValue;
public class IntegerType implements IType {
//#region Exposed Methods
public boolean equals(Object other){
return other instanceof IntegerType;
}
public String toString(){
return "int";
}
public IValue defaultValue(){
return new IntegerValue(0);
}
}
@@ -0,0 +1,33 @@
package Models.Types;
import Models.Values.IValue;
import Models.Values.ReferenceValue;
public class ReferenceType implements IType {
private IType innerType;
public ReferenceType(IType innerType) {
this.innerType = innerType;
}
public IType getInnerType() {
return this.innerType;
}
public boolean equals(Object other) {
if (other instanceof ReferenceType) {
return this.innerType.equals(((ReferenceType)other).getInnerType());
}
return false;
}
public String toString() {
return "Ref(" + this.innerType.toString() + ")";
}
public IValue defaultValue() {
return new ReferenceValue(0, this.innerType);
}
}
@@ -0,0 +1,18 @@
package Models.Types;
import Models.Values.IValue;
import Models.Values.StringValue;
public class StringType implements IType {
public boolean equals(Object another) {
return another instanceof StringType;
}
public String toString() {
return "string";
}
public IValue defaultValue() {
return new StringValue("");
}
}
@@ -0,0 +1,35 @@
package Models.Values;
import Models.Types.IType;
import Models.Types.BooleanType;
public class BooleanValue implements IValue {
//#region Fields
private boolean value;
//#endregion
//#region Exposed Methods
public BooleanValue(boolean value){
this.value = value;
}
public boolean getValue(){
return this.value;
}
public String toString(){
return Boolean.toString(this.value);
}
public IType getType(){
return new BooleanType();
}
public boolean equals(Object other){
if(other instanceof BooleanValue){
var otherValue = (BooleanValue)other;
return otherValue.getValue() == this.value;
}
return false;
}
//#endregion
}
@@ -0,0 +1,7 @@
package Models.Values;
import Models.Types.IType;
public interface IValue {
public IType getType();
}
@@ -0,0 +1,36 @@
package Models.Values;
import Models.Types.IType;
import Models.Types.IntegerType;
public class IntegerValue implements IValue {
//#region Fields
private int value;
//#endregion
//#region Exposed Methods
public IntegerValue(int value){
this.value = value;
}
public int getValue(){
return this.value;
}
public String toString(){
return Integer.toString(this.value);
}
public IType getType(){
return new IntegerType();
}
public boolean equals(Object other){
if(other instanceof IntegerValue){
var otherValue = (IntegerValue)other;
return otherValue.getValue() == this.value;
}
return false;
}
//#endregion
}
@@ -0,0 +1,22 @@
package Models.Values;
import Models.Types.IType;
import Models.Types.ReferenceType;
public class ReferenceValue implements IValue {
private Integer address;
private IType locationType;
public ReferenceValue(Integer address, IType locationType) {
this.address = address;
this.locationType = locationType;
}
public Integer getAddress() {
return this.address;
}
public IType getType() {
return new ReferenceType(this.locationType);
}
}
@@ -0,0 +1,44 @@
package Models.Values;
import Models.Types.IType;
import Models.Types.StringType;
public class StringValue implements IValue {
private String value;
public StringValue(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
public boolean equals(Object other) {
if (other instanceof StringValue) {
var otherValue = (StringValue) other;
return otherValue.getValue().equals(this.value);
}
return false;
}
public String toString() {
return this.value;
}
public IValue copy() {
return new StringValue(this.value);
}
public IType getType() {
return new StringType();
}
public boolean equals(IValue other) {
if (other instanceof StringValue) {
var otherValue = (StringValue) other;
return otherValue.getValue().equals(this.value);
}
return false;
}
}
@@ -0,0 +1,13 @@
package Repositories;
import java.util.List;
import Exceptions.BaseException;
import Models.Program.ProgramState;
public interface IRepository {
public void addProgramState(ProgramState programState) throws BaseException;
public void logProgramStateExecution(ProgramState state) throws BaseException;
public List<ProgramState> getProgramStates();
public void setProgramStates(List<ProgramState> programStates);
}
@@ -0,0 +1,51 @@
package Repositories;
import Models.Program.ProgramState;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import Exceptions.BaseException;
public class Repository implements IRepository {
private List<ProgramState> programStates;
private String logFilePath;
public Repository() {
this.programStates = new ArrayList<ProgramState>();
this.logFilePath = "log.txt";
}
public Repository(String logFilePath) {
this.programStates = new ArrayList<ProgramState>();
this.logFilePath = logFilePath;
}
public void addProgramState(ProgramState programState) throws BaseException {
programState.typeCheck();
programStates.clear();
programStates.add(programState);
}
public List<ProgramState> getProgramStates() {
return programStates;
}
public void setProgramStates(List<ProgramState> programStates) {
this.programStates = programStates;
}
public void logProgramStateExecution(ProgramState state) throws BaseException{
try{
var logFile = new PrintWriter(new BufferedWriter(new FileWriter(this.logFilePath, true)));
logFile.println(state.toString());
logFile.close();
}
catch(Exception exception){
throw new BaseException(exception.getMessage());
}
}
}
@@ -0,0 +1,17 @@
package Views.Commands;
public abstract class Command {
private String key;
private String description;
public Command (String key, String description) {
this.key = key;
this.description = description;
}
public abstract void execute();
public String getKey() {
return this.key;
}
public String getDescription() {
return this.description;
}
}
@@ -0,0 +1,12 @@
package Views.Commands;
public class ExitCommand extends Command {
public ExitCommand(String key, String description) {
super(key, description);
}
@Override
public void execute() {
System.exit(0);
}
}
@@ -0,0 +1,16 @@
package Views.Commands;
import Controllers.Controller;
public class RunExampleCommand extends Command {
private Controller controller;
public RunExampleCommand(String key, String description, Controller controller) {
super(key, description);
this.controller = controller;
}
@Override
public void execute() {
this.controller.allSteps();
}
}
@@ -0,0 +1,38 @@
package Views;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import Views.Commands.Command;
public class TextMenu {
private Map<String, Command> commands;
public TextMenu() {
this.commands = new HashMap<String, Command>();
}
public void addCommand(Command command) {
this.commands.put(command.getKey(), command);
}
private void printMenu() {
System.out.println("Menu:");
for (Command command : this.commands.values()) {
String line = String.format("%4s: %s", command.getKey(), command.getDescription());
System.out.println(line);
}
}
public void show() {
var scanner = new Scanner(System.in);
while (true) {
this.printMenu();
System.out.println("Input the option: ");
String key = scanner.nextLine();
Command command = this.commands.get(key);
if (command == null) {
System.out.println("Invalid option");
continue;
}
command.execute();
}
}
}
@@ -0,0 +1,2 @@
15
50
@@ -0,0 +1,41 @@
package Controller;
import Model.IVehicle;
import Repository.IRepository;
public class Controller {
private IRepository _repository;
public Controller(IRepository repository) {
this._repository = repository;
}
public void addVehicle(IVehicle vehicle) throws IllegalArgumentException {
_repository.add(vehicle);
}
public void removeVehicle(int index) throws IllegalArgumentException {
_repository.remove(index);
}
public IVehicle[] getAllVehicles() {
return _repository.getAll();
}
public IVehicle[] filterVehicles(String color){
IVehicle[] vehicles = _repository.getAll();
IVehicle[] filteredVehicles = new IVehicle[_repository.getSize()];
int index = 0;
for(IVehicle vehicle : vehicles) {
if(vehicle.getColor().equals(color)) {
filteredVehicles[index++] = vehicle;
}
}
IVehicle[] copy = new IVehicle[index];
for(int i = 0; i < index; i++) {
copy[i] = filteredVehicles[i];
}
return copy;
}
}
@@ -0,0 +1,43 @@
package Model;
public class Bicycle implements IVehicle {
private String _brand;
private String _color;
public Bicycle(String brand, String color) {
this._brand = brand;
this._color = color;
}
public String getBrand() {
return this._brand;
}
public void setBrand(String brand) throws IllegalArgumentException {
if (brand == null || brand.length() < 3) {
throw new IllegalArgumentException("Brand must be at least 3 characters long");
}
this._brand = brand;
}
public String getColor() {
return this._color;
}
public void setColor(String color) throws IllegalArgumentException {
if (color == null || color.length() < 3) {
throw new IllegalArgumentException("Color must be at least 3 characters long");
}
this._color = color;
}
@Override
public String toString() {
return "Bicycle{" +
"brand='" + _brand + '\'' +
", color='" + _color + '\'' +
'}';
}
}
@@ -0,0 +1,43 @@
package Model;
public class Car implements IVehicle {
private String _brand;
private String _color;
public Car(String brand, String color) {
this._brand = brand;
this._color = color;
}
public String getBrand() {
return this._brand;
}
public void setBrand(String brand) throws IllegalArgumentException {
if (brand == null || brand.length() < 3) {
throw new IllegalArgumentException("Brand must be at least 3 characters long");
}
this._brand = brand;
}
public String getColor() {
return this._color;
}
public void setColor(String color) throws IllegalArgumentException {
if (color == null || color.length() < 3) {
throw new IllegalArgumentException("Color must be at least 3 characters long");
}
this._color = color;
}
@Override
public String toString() {
return "Car{" +
"brand='" + _brand + '\'' +
", color='" + _color + '\'' +
'}';
}
}
@@ -0,0 +1,8 @@
package Model;
public interface IVehicle {
String getBrand();
void setBrand(String brand) throws IllegalArgumentException;
String getColor();
void setColor(String color) throws IllegalArgumentException;
}
@@ -0,0 +1,43 @@
package Model;
public class Motorcycle implements IVehicle{
private String _brand;
private String _color;
public Motorcycle(String brand, String color) {
this._brand = brand;
this._color = color;
}
public String getBrand() {
return this._brand;
}
public void setBrand(String brand) throws IllegalArgumentException {
if (brand == null || brand.length() < 3) {
throw new IllegalArgumentException("Brand must be at least 3 characters long");
}
this._brand = brand;
}
public String getColor() {
return this._color;
}
public void setColor(String color) throws IllegalArgumentException {
if (color == null || color.length() < 3) {
throw new IllegalArgumentException("Color must be at least 3 characters long");
}
this._color = color;
}
@Override
public String toString() {
return "Motorcycle{" +
"brand='" + _brand + '\'' +
", color='" + _color + '\'' +
'}';
}
}
@@ -0,0 +1,10 @@
package Repository;
import Model.IVehicle;
public interface IRepository {
public void add(IVehicle vehicle) throws IllegalArgumentException;
public void remove(int index) throws IllegalArgumentException;
public IVehicle[] getAll();
public int getSize();
}
@@ -0,0 +1,58 @@
package Repository;
import Model.IVehicle;
public class VehicleRepo implements IRepository {
private IVehicle[] _vehicles;
private Integer _capacity;
private Integer _size;
public VehicleRepo(Integer capacity) throws IllegalArgumentException {
if(capacity < 0) {
throw new IllegalArgumentException("Capacity must be a positive number");
}
this._capacity = capacity;
this._vehicles = new IVehicle[capacity];
this._size = 0;
}
@Override
public void add(IVehicle vehicle) throws IllegalArgumentException {
if(_size == _capacity) {
throw new IllegalArgumentException("Repository is full");
}
_vehicles[_size] = vehicle;
_size++;
}
@Override
public void remove(int index) throws IllegalArgumentException {
if(_size == 0) {
throw new IllegalArgumentException("Repository is empty");
}
if(index < 0 || index > _size) {
throw new IllegalArgumentException("Index out of bounds");
}
for(int i = index; i < _size - 1; i++) {
_vehicles[i] = _vehicles[i + 1];
}
_size--;
}
@Override
public IVehicle[] getAll() {
IVehicle[] copy = new IVehicle[_size];
for(int i = 0; i < _size; i++) {
copy[i] = _vehicles[i];
}
return copy;
}
@Override
public int getSize() {
return _size;
}
}
@@ -0,0 +1,41 @@
package View;
import Controller.Controller;
import Model.Car;
import Model.IVehicle;
import Model.Motorcycle;
import Model.Bicycle;
import Repository.IRepository;
import Repository.VehicleRepo;
public class View {
public static void main(String[] args) {
IRepository repo;
try{
repo = new VehicleRepo(-5);
}
catch(IllegalArgumentException e) {
System.out.println(e.getMessage());
return;
}
Controller controller = new Controller(repo);
Car car = new Car("BMW", "Red");
Motorcycle motorcycle = new Motorcycle("Honda", "Black");
Bicycle bicycle = new Bicycle("Trek", "Blue");
Bicycle bicycle2 = new Bicycle("Trek", "Red");
try{
controller.addVehicle(car);
controller.addVehicle(motorcycle);
controller.addVehicle(bicycle);
controller.addVehicle(bicycle2);
}
catch(IllegalArgumentException e) {
System.out.println(e.getMessage());
return;
}
IVehicle[] filteredVehicles = controller.filterVehicles("Red");
for(IVehicle vehicle : filteredVehicles) {
System.out.println(vehicle.toString());
}
}
}
@@ -0,0 +1,3 @@
/target
*.in
*.txt
@@ -0,0 +1,51 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>gui_interpretor</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>13</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>13</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>11</release>
</configuration>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.6</version>
<executions>
<execution>
<!-- Default configuration for running -->
<!-- Usage: mvn clean javafx:run -->
<id>default-cli</id>
<configuration>
<mainClass>com.example.App</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,39 @@
package com.example;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class App extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader listLoader = new FXMLLoader();
listLoader.setLocation(getClass().getResource("listView.fxml"));
Parent root = listLoader.load();
ListController listController = listLoader.getController();
primaryStage.setTitle("Select");
primaryStage.setScene(new Scene(root, 500, 550));
primaryStage.show();
FXMLLoader programLoader = new FXMLLoader();
programLoader.setLocation(getClass().getResource("programView.fxml"));
Parent programRoot = programLoader.load();
ProgramController programController = programLoader.getController();
listController.setProgramController(programController);
Stage secondaryStage = new Stage();
secondaryStage.setTitle("Interpreter");
secondaryStage.setScene(new Scene(programRoot, 1920, 1000));
secondaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
@@ -0,0 +1,116 @@
package com.example.Controllers;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.example.Exceptions.BaseException;
import com.example.Models.Program.ProgramState;
import com.example.Models.Values.IValue;
import com.example.Models.Values.ReferenceValue;
import com.example.Repositories.IRepository;
public class Controller {
private IRepository repository;
private boolean displayFlag;
private ExecutorService executor;
public Controller(IRepository repository, boolean displayFlag) {
this.repository = repository;
this.displayFlag = displayFlag;
}
public List<ProgramState> getProgramStates(){
return repository.getProgramStates();
}
public List<ProgramState> removeCompletedPrograms(List<ProgramState> programStates) {
return programStates.stream().filter(p -> p.isNotCompleted()).collect(Collectors.toList());
}
public void oneStepForAllProgramStates(List<ProgramState> programStates) {
programStates = programStates.stream().filter(p -> p != null).collect(Collectors.toList());
programStates.forEach(programState -> {
try{
repository.logProgramStateExecution(programState);
}
catch(BaseException e){
System.out.println(e.getMessage());
}
});
List<Callable<ProgramState>> callList = programStates.stream().map((ProgramState p) -> (Callable<ProgramState>)(() -> {
try{
return p.oneStep();
}
catch(BaseException e){
System.out.println(e.getMessage());
}
return null;
})).filter(c -> c != null).collect(Collectors.toList());
List<ProgramState> newProgramStates = new ArrayList<ProgramState>();
try{
newProgramStates = executor.invokeAll(callList).stream().map(future -> {
try {
return future.get();
} catch (Exception e) {
System.out.println(e.getMessage());
}
return null;
}).filter(p -> p != null).collect(Collectors.toList());
}
catch(InterruptedException e){
System.out.println(e.getMessage());
}
programStates.addAll(newProgramStates);
programStates.forEach(programState -> {
try{
repository.logProgramStateExecution(programState);
}
catch(BaseException e){
System.out.println(e.getMessage());
}
});
repository.setProgramStates(programStates);
}
public void oneStepAll(){
executor = Executors.newFixedThreadPool(2);
List<ProgramState> programStates = removeCompletedPrograms(repository.getProgramStates());
programStates.get(0).getHeap().setContent(this.garbageCollector(this.getAddressesFromSymbolTable(programStates.stream().map(programState -> programState.getSymbolTable().getContent()).collect(Collectors.toList()), programStates.get(0).getHeap().getContent()), programStates.get(0).getHeap().getContent()));
oneStepForAllProgramStates(programStates);
executor.shutdownNow();
//repository.setProgramStates(programStates);
}
public void allSteps() {
executor = Executors.newFixedThreadPool(2);
List<ProgramState> programStates = removeCompletedPrograms(repository.getProgramStates());
while(programStates.size() > 0){
programStates.get(0).getHeap().setContent(this.garbageCollector(this.getAddressesFromSymbolTable(programStates.stream().map(programState -> programState.getSymbolTable().getContent()).collect(Collectors.toList()), programStates.get(0).getHeap().getContent()), programStates.get(0).getHeap().getContent()));
oneStepForAllProgramStates(programStates);
programStates = removeCompletedPrograms(repository.getProgramStates());
}
executor.shutdownNow();
repository.setProgramStates(programStates);
}
public Hashtable<Integer, IValue> garbageCollector(Set<Integer> symbolTable, Hashtable<Integer, IValue> heap) {
return heap.entrySet().stream().filter(e -> symbolTable.contains(e.getKey()))
.collect(Hashtable::new, (m, e) -> m.put(e.getKey(), e.getValue()), Hashtable::putAll);
}
public Set<Integer> getAddressesFromSymbolTable(List<Collection<IValue>> symbolTablesValues, Hashtable<Integer, IValue> heap) {
return symbolTablesValues.stream().flatMap(Collection::stream).filter(v -> v instanceof ReferenceValue)
.flatMap(v -> Stream.iterate(((ReferenceValue) v).getAddress(), Objects::nonNull, addr -> {
var value = heap.get(addr);
return value instanceof ReferenceValue ? ((ReferenceValue) value).getAddress() : null;
})).distinct().collect(Collectors.toSet());
}
}
@@ -0,0 +1,70 @@
package com.example;
import com.example.Models.Expressions.ArithmeticExpression;
import com.example.Models.Expressions.ReadHeap;
import com.example.Models.Expressions.RelationalExpression;
import com.example.Models.Expressions.ValueExpression;
import com.example.Models.Expressions.VariableExpression;
import com.example.Models.Statements.AquireStatement;
import com.example.Models.Statements.AssignmentStatement;
import com.example.Models.Statements.CloseReadFileStatement;
import com.example.Models.Statements.CompoundStatement;
import com.example.Models.Statements.CreateSemaphore;
import com.example.Models.Statements.ForkStatement;
import com.example.Models.Statements.IStatement;
import com.example.Models.Statements.IfStatement;
import com.example.Models.Statements.NewStatement;
import com.example.Models.Statements.OpenReadFileStatement;
import com.example.Models.Statements.PrintStatement;
import com.example.Models.Statements.ReadFileStatement;
import com.example.Models.Statements.ReleaseStatement;
import com.example.Models.Statements.SwitchStatement;
import com.example.Models.Statements.VariableDeclarationStatement;
import com.example.Models.Statements.WhileStatement;
import com.example.Models.Statements.WriteHeap;
import com.example.Models.Types.BooleanType;
import com.example.Models.Types.IntegerType;
import com.example.Models.Types.ReferenceType;
import com.example.Models.Types.StringType;
import com.example.Models.Values.BooleanValue;
import com.example.Models.Values.IntegerValue;
import com.example.Models.Values.StringValue;
public class Examples{
public static IStatement[] exampleList() {
IStatement ex1= new CompoundStatement(new VariableDeclarationStatement("v", new IntegerType()), new CompoundStatement(new AssignmentStatement("v", new ValueExpression(new IntegerValue((2)))), new PrintStatement(new VariableExpression(("v")))));
IStatement ex2 = new CompoundStatement( new VariableDeclarationStatement("a",new IntegerType()),
new CompoundStatement(new VariableDeclarationStatement("b",new IntegerType()),
new CompoundStatement(new AssignmentStatement("a", new ArithmeticExpression('+',new ValueExpression(new IntegerValue(2)),new
ArithmeticExpression('*',new ValueExpression(new IntegerValue(3)), new ValueExpression(new IntegerValue(5))))),
new CompoundStatement(new AssignmentStatement("b",new ArithmeticExpression('+',new VariableExpression("a"), new ValueExpression(new
IntegerValue(1)))), new PrintStatement(new VariableExpression("b"))))));
IStatement ex3 = new CompoundStatement(new VariableDeclarationStatement("a",new BooleanType()),
new CompoundStatement(new VariableDeclarationStatement("v", new IntegerType()),
new CompoundStatement(new AssignmentStatement("a", new ValueExpression(new BooleanValue(true))),
new CompoundStatement(new IfStatement(new VariableExpression("a"),new AssignmentStatement("v",new ValueExpression(new
IntegerValue(2))), new AssignmentStatement("v", new ValueExpression(new IntegerValue(3)))), new PrintStatement(new
VariableExpression("v"))))));
IStatement ex4 = new CompoundStatement(new VariableDeclarationStatement("varf", new StringType()), new CompoundStatement(new AssignmentStatement("varf", new ValueExpression(new StringValue("test.in"))), new CompoundStatement(new OpenReadFileStatement(new VariableExpression("varf")), new CompoundStatement(new VariableDeclarationStatement("varc", new IntegerType()), new CompoundStatement(new ReadFileStatement(new VariableExpression("varf"), "varc"), new CompoundStatement(new PrintStatement(new VariableExpression("varc")), new CompoundStatement(new ReadFileStatement(new VariableExpression("varf"), "varc"), new CompoundStatement(new PrintStatement(new VariableExpression("varc")), new CloseReadFileStatement(new VariableExpression("varf"))))))))));
IStatement ex5 = new CompoundStatement(new IfStatement(new RelationalExpression(new ValueExpression(new IntegerValue(1)), new ValueExpression(new IntegerValue(2)), "<"), new PrintStatement(new ValueExpression(new IntegerValue(1))),new PrintStatement(new ValueExpression(new IntegerValue(2)))), new PrintStatement(new ValueExpression(new IntegerValue(3))));
IStatement ex6 = new CompoundStatement(new VariableDeclarationStatement("v", new ReferenceType(new IntegerType())), new CompoundStatement(new NewStatement("v", new ValueExpression(new IntegerValue(20))), new CompoundStatement(new VariableDeclarationStatement("a", new ReferenceType(new ReferenceType(new IntegerType()))), new CompoundStatement(new NewStatement("a", new VariableExpression("v")), new CompoundStatement(new NewStatement("v", new ValueExpression(new IntegerValue(30))), new PrintStatement(new ReadHeap(new ReadHeap(new VariableExpression("a")))))))));
IStatement ex7 = new CompoundStatement(new VariableDeclarationStatement("v", new ReferenceType(new IntegerType())), new CompoundStatement(new NewStatement("v", new ValueExpression(new IntegerValue(10))), new CompoundStatement(new NewStatement("v", new ValueExpression(new IntegerValue(20))), new PrintStatement(new VariableExpression("v")))));
IStatement ex8 = new CompoundStatement(new VariableDeclarationStatement("v", new IntegerType()), new CompoundStatement(new AssignmentStatement("v", new ValueExpression(new IntegerValue(4))), new CompoundStatement(new WhileStatement(new CompoundStatement(new PrintStatement(new VariableExpression("v")), new AssignmentStatement("v", new ArithmeticExpression('-', new VariableExpression("v"), new ValueExpression(new IntegerValue(1))))), new RelationalExpression(new VariableExpression("v"), new ValueExpression(new IntegerValue(0)), ">")), new PrintStatement(new VariableExpression("v")))));
IStatement ex9 = new CompoundStatement(new VariableDeclarationStatement("v", new IntegerType()), new CompoundStatement(new VariableDeclarationStatement("a", new ReferenceType(new IntegerType())), new CompoundStatement(new AssignmentStatement("v", new ValueExpression(new IntegerValue(10))), new CompoundStatement(new NewStatement("a", new ValueExpression(new IntegerValue(22))), new CompoundStatement(new ForkStatement(new CompoundStatement(new WriteHeap("a", new ValueExpression(new IntegerValue(30))), new CompoundStatement(new AssignmentStatement("v", new ValueExpression(new IntegerValue(32))), new CompoundStatement(new PrintStatement(new VariableExpression("v")), new PrintStatement(new ReadHeap(new VariableExpression("a"))))))), new CompoundStatement(new PrintStatement(new VariableExpression("v")), new PrintStatement(new ReadHeap(new VariableExpression("a")))))))));
IStatement ex10 = new CompoundStatement(new VariableDeclarationStatement("v1", new ReferenceType(new IntegerType())), new CompoundStatement(new VariableDeclarationStatement("cnt", new IntegerType()), new CompoundStatement(new NewStatement("v1", new ValueExpression(new IntegerValue(1))), new CompoundStatement(new CreateSemaphore("cnt", new ReadHeap(new VariableExpression("v1"))), new CompoundStatement(new ForkStatement(new CompoundStatement(new AquireStatement("cnt"), new CompoundStatement(new WriteHeap("v1", new ArithmeticExpression('*', new ReadHeap(new VariableExpression("v1")), new ValueExpression(new IntegerValue(10)))), new CompoundStatement(new PrintStatement(new ReadHeap(new VariableExpression("v1"))), new ReleaseStatement("cnt"))))), new CompoundStatement(new ForkStatement(new CompoundStatement(new AquireStatement("cnt"), new CompoundStatement(new WriteHeap("v1",new ArithmeticExpression('*', new ReadHeap(new VariableExpression("v1")), new ValueExpression(new IntegerValue(10)))), new CompoundStatement(new WriteHeap("v1", new ArithmeticExpression('*', new ReadHeap(new VariableExpression("v1")), new ValueExpression(new IntegerValue(2)))), new CompoundStatement(new PrintStatement(new ReadHeap(new VariableExpression("v1"))), new ReleaseStatement("cnt")))))), new CompoundStatement(new AquireStatement("cnt"), new CompoundStatement(new PrintStatement(new ArithmeticExpression('-', new ReadHeap(new VariableExpression("v1")), new ValueExpression(new IntegerValue(1)))), new ReleaseStatement("cnt")))))))));
IStatement ex11 = new CompoundStatement(new VariableDeclarationStatement("a", new IntegerType()), new CompoundStatement(new VariableDeclarationStatement("b", new IntegerType()), new CompoundStatement(new VariableDeclarationStatement("c", new IntegerType()), new CompoundStatement(new AssignmentStatement("a", new ValueExpression(new IntegerValue(1))), new CompoundStatement(new AssignmentStatement("b", new ValueExpression(new IntegerValue(2))), new CompoundStatement(new AssignmentStatement("c", new ValueExpression(new IntegerValue(5))), new CompoundStatement(new SwitchStatement(new ArithmeticExpression('*', new VariableExpression("a"), new ValueExpression(new IntegerValue(10))), new ArithmeticExpression('*', new VariableExpression("b"), new VariableExpression("c")), new ValueExpression(new IntegerValue(10)), new CompoundStatement(new PrintStatement(new VariableExpression("a")), new PrintStatement(new VariableExpression("b"))), new CompoundStatement(new PrintStatement(new ValueExpression(new IntegerValue(100))), new PrintStatement(new ValueExpression(new IntegerValue(200)))), new PrintStatement(new ValueExpression(new IntegerValue(300)))), new PrintStatement(new ValueExpression(new IntegerValue(300))))))))));
return new IStatement[]{ex1, ex2, ex3, ex4, ex5, ex6, ex7, ex8, ex9, ex10, ex11};
}
}
@@ -0,0 +1,7 @@
package com.example.Exceptions;
public class BaseException extends Throwable {
public BaseException(String message) {
super(message);
}
}
@@ -0,0 +1,62 @@
package com.example;
import java.io.BufferedReader;
import java.io.IOException;
import com.example.Controllers.Controller;
import com.example.Exceptions.BaseException;
import com.example.Models.Program.GenericDictionary;
import com.example.Models.Program.GenericQueue;
import com.example.Models.Program.GenericStack;
import com.example.Models.Program.Heap;
import com.example.Models.Program.ProgramState;
import com.example.Models.Program.SemaphoreTable;
import com.example.Models.Statements.IStatement;
import com.example.Models.Values.IValue;
import com.example.Models.Values.StringValue;
import com.example.Repositories.IRepository;
import com.example.Repositories.Repository;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ListView;
import javafx.scene.layout.Region;
public class ListController {
private ProgramController programController;
public void setProgramController(ProgramController programController) {
this.programController = programController;
}
@FXML
private ListView<IStatement> statements;
@FXML
private Button displayButton;
@FXML
public void initialize() {
statements.setItems(FXCollections.observableArrayList(Examples.exampleList()));
displayButton.setOnAction(actionEvent -> {
int index = statements.getSelectionModel().getSelectedIndex();
if (index < 0)
return;
try{
ProgramState state = new ProgramState(new GenericStack<IStatement>(), new GenericDictionary<String, IValue>(), new GenericQueue<IValue>(), new GenericDictionary<StringValue, BufferedReader>(), new Heap(), new SemaphoreTable(), Examples.exampleList()[index]);
IRepository repository = new Repository("log.txt");
repository.addProgramState(state);
Controller controller = new Controller(repository, true);
programController.setController(controller);
} catch (BaseException interpreterError) {
Alert alert = new Alert(Alert.AlertType.ERROR, interpreterError.getMessage(), ButtonType.OK);
alert.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
alert.showAndWait();
}
});
}
}
@@ -0,0 +1,77 @@
package com.example.Models.Expressions;
import com.example.Exceptions.BaseException;
import com.example.Models.Program.IDictionary;
import com.example.Models.Program.IHeap;
import com.example.Models.Types.IType;
import com.example.Models.Types.IntegerType;
import com.example.Models.Values.IntegerValue;
import com.example.Models.Values.IValue;
public class ArithmeticExpression implements IExpression {
private IExpression left;
private IExpression right;
private char operator;
public ArithmeticExpression(char operator,IExpression left, IExpression right) {
this.left = left;
this.right = right;
this.operator = operator;
}
public IValue evaluate(IDictionary<String, IValue> table, IHeap heap) throws BaseException {
IValue leftValue = left.evaluate(table, heap);
IValue rightValue = right.evaluate(table, heap);
if (leftValue.getType().equals(new IntegerType())) {
int leftInt = ((IntegerValue)leftValue).getValue();
if (rightValue.getType().equals(new IntegerType())) {
int rightInt = ((IntegerValue)rightValue).getValue();
switch (operator) {
case '+':
return new IntegerValue(leftInt + rightInt);
case '-':
return new IntegerValue(leftInt - rightInt);
case '*':
return new IntegerValue(leftInt * rightInt);
case '/':
if (rightInt == 0) {
throw new BaseException("Division by zero!");
}
return new IntegerValue(leftInt / rightInt);
default:
throw new BaseException("Invalid operator!");
}
} else {
throw new BaseException("Second operand is not an integer!");
}
} else {
throw new BaseException("First operand is not an integer!");
}
}
public IExpression copy() {
return new ArithmeticExpression(operator, left.copy(), right.copy());
}
public String toString() {
return left.toString() + " " + operator + " " + right.toString();
}
public IType typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
IType type1, type2;
type1 = left.typeCheck(typeTable);
type2 = right.typeCheck(typeTable);
if (type1.equals(new IntegerType())) {
if (type2.equals(new IntegerType())) {
return new IntegerType();
} else {
throw new BaseException("Second operand is not an integer!");
}
} else {
throw new BaseException("First operand is not an integer!");
}
}
}
@@ -0,0 +1,13 @@
package com.example.Models.Expressions;
import com.example.Exceptions.BaseException;
import com.example.Models.Program.IDictionary;
import com.example.Models.Program.IHeap;
import com.example.Models.Types.IType;
import com.example.Models.Values.IValue;
public interface IExpression {
public IValue evaluate(IDictionary<String, IValue> table, IHeap heap) throws BaseException;
public IType typeCheck(IDictionary<String, IType> typeTable) throws BaseException;
public IExpression copy();
}
@@ -0,0 +1,70 @@
package com.example.Models.Expressions;
import com.example.Exceptions.BaseException;
import com.example.Models.Program.IDictionary;
import com.example.Models.Program.IHeap;
import com.example.Models.Types.BooleanType;
import com.example.Models.Types.IType;
import com.example.Models.Values.BooleanValue;
import com.example.Models.Values.IValue;
public class LogicExpression implements IExpression {
private IExpression left;
private IExpression right;
private String operator;
public LogicExpression(IExpression left, IExpression right, String operator) {
this.left = left;
this.right = right;
this.operator = operator;
}
public IValue evaluate(IDictionary<String, IValue> table, IHeap heap) throws BaseException {
IValue leftValue = left.evaluate(table, heap);
IValue rightValue = right.evaluate(table, heap);
if (leftValue.getType().equals(new BooleanType())) {
boolean leftBool = ((BooleanValue)leftValue).getValue();
if (rightValue.getType().equals(new BooleanType())) {
boolean rightBool = ((BooleanValue)rightValue).getValue();
switch (operator) {
case "&&":
return new BooleanValue(leftBool && rightBool);
case "||":
return new BooleanValue(leftBool || rightBool);
default:
throw new BaseException("Invalid operator!");
}
} else {
throw new BaseException("Second operand is not a boolean!");
}
} else {
throw new BaseException("First operand is not a boolean!");
}
}
public IExpression copy() {
return new LogicExpression(left.copy(), right.copy(), operator);
}
public String toString() {
return left.toString() + " " + operator + " " + right.toString();
}
public IType typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
IType leftType, rightType;
leftType = left.typeCheck(typeTable);
rightType = right.typeCheck(typeTable);
if (leftType.equals(new BooleanType())) {
if (rightType.equals(new BooleanType())) {
return new BooleanType();
} else {
throw new BaseException("Second operand is not a boolean!");
}
} else {
throw new BaseException("First operand is not a boolean!");
}
}
}
@@ -0,0 +1,44 @@
package com.example.Models.Expressions;
import com.example.Exceptions.BaseException;
import com.example.Models.Program.IDictionary;
import com.example.Models.Program.IHeap;
import com.example.Models.Types.IType;
import com.example.Models.Types.ReferenceType;
import com.example.Models.Values.IValue;
import com.example.Models.Values.ReferenceValue;
public class ReadHeap implements IExpression {
private IExpression expression;
public ReadHeap(IExpression expression) {
this.expression = expression;
}
public String toString() {
return "rH(" + expression + ")";
}
public IValue evaluate(IDictionary<String, IValue> table, IHeap heap) throws BaseException {
IValue value = this.expression.evaluate(table, heap);
if(!(value instanceof ReferenceValue)) {
throw new BaseException("Expression is not a reference value");
}
int address = ((ReferenceValue)value).getAddress();
if(!heap.contains(address)) {
throw new BaseException("Address " + address + " is not in the heap");
}
return heap.get(address);
}
public IExpression copy() {
return new ReadHeap(this.expression.copy());
}
public IType typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
IType type = this.expression.typeCheck(typeTable);
if(!(type instanceof ReferenceType)) {
throw new BaseException("Expression is not a reference value");
}
return ((ReferenceType)type).getInnerType();
}
}
@@ -0,0 +1,71 @@
package com.example.Models.Expressions;
import com.example.Exceptions.BaseException;
import com.example.Models.Program.IDictionary;
import com.example.Models.Program.IHeap;
import com.example.Models.Types.BooleanType;
import com.example.Models.Types.IType;
import com.example.Models.Types.IntegerType;
import com.example.Models.Values.BooleanValue;
import com.example.Models.Values.IValue;
import com.example.Models.Values.IntegerValue;
public class RelationalExpression implements IExpression {
private IExpression leftExpression;
private IExpression rightExpression;
private String operator;
public RelationalExpression(IExpression leftExpression, IExpression rightExpression, String operator) {
this.leftExpression = leftExpression;
this.rightExpression = rightExpression;
this.operator = operator;
}
public IExpression copy() {
return new RelationalExpression(this.leftExpression.copy(), this.rightExpression.copy(), this.operator);
}
public String toString() {
return this.leftExpression.toString() + " " + this.operator + " " + this.rightExpression.toString();
}
public IValue evaluate(IDictionary<String, IValue> symbolTable, IHeap heap) throws BaseException {
var leftValue = this.leftExpression.evaluate(symbolTable, heap);
var rightValue = this.rightExpression.evaluate(symbolTable, heap);
if (leftValue.getType().equals(new IntegerType()) && rightValue.getType().equals(new IntegerType())) {
var leftIntegerValue = (IntegerValue) leftValue;
var rightIntegerValue = (IntegerValue) rightValue;
var leftInteger = leftIntegerValue.getValue();
var rightInteger = rightIntegerValue.getValue();
switch (this.operator) {
case "<":
return new BooleanValue(leftInteger < rightInteger);
case "<=":
return new BooleanValue(leftInteger <= rightInteger);
case "==":
return new BooleanValue(leftInteger == rightInteger);
case "!=":
return new BooleanValue(leftInteger != rightInteger);
case ">":
return new BooleanValue(leftInteger > rightInteger);
case ">=":
return new BooleanValue(leftInteger >= rightInteger);
default:
throw new BaseException("RelationalExpression: Invalid operator");
}
}
throw new BaseException("RelationalExpression: Operands are not of type IntegerType");
}
public IType typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
var leftType = this.leftExpression.typeCheck(typeTable);
var rightType = this.rightExpression.typeCheck(typeTable);
if (leftType.equals(new IntegerType())) {
if (rightType.equals(new IntegerType())) {
return new BooleanType();
}
throw new BaseException("RelationalExpression: Right operand is not of type IntegerType");
}
throw new BaseException("RelationalExpression: Left operand is not of type IntegerType");
}
}
@@ -0,0 +1,31 @@
package com.example.Models.Expressions;
import com.example.Models.Values.IValue;
import com.example.Exceptions.BaseException;
import com.example.Models.Program.IDictionary;
import com.example.Models.Program.IHeap;
import com.example.Models.Types.IType;
public class ValueExpression implements IExpression {
private IValue value;
public ValueExpression(IValue value) {
this.value = value;
}
public IValue evaluate(IDictionary<String, IValue> table, IHeap heap) throws BaseException {
return value;
}
public IExpression copy() {
return new ValueExpression(value);
}
public String toString() {
return value.toString();
}
public IType typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
return value.getType();
}
}
@@ -0,0 +1,31 @@
package com.example.Models.Expressions;
import com.example.Exceptions.BaseException;
import com.example.Models.Program.IDictionary;
import com.example.Models.Program.IHeap;
import com.example.Models.Types.IType;
import com.example.Models.Values.IValue;
public class VariableExpression implements IExpression {
private String name;
public VariableExpression(String name) {
this.name = name;
}
public IValue evaluate(IDictionary<String, IValue> table, IHeap heap) throws BaseException {
return table.get(name);
}
public IExpression copy() {
return new VariableExpression(name);
}
public String toString() {
return name;
}
public IType typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
return typeTable.get(name);
}
}
@@ -0,0 +1,76 @@
package com.example.Models.Program;
import com.example.Exceptions.BaseException;
import java.util.Collection;
import java.util.Hashtable;
public class GenericDictionary<K, V> implements IDictionary<K, V> {
private Hashtable<K, V> dictionary;
public GenericDictionary() {
dictionary = new Hashtable<K, V>();
}
public void add(K key, V value) throws BaseException {
if (dictionary.containsKey(key)) {
throw new BaseException("Key already exists in dictionary.");
}
dictionary.put(key, value);
}
public void update(K key, V value) throws BaseException {
if (!dictionary.containsKey(key)) {
throw new BaseException("Key does not exist in dictionary.");
}
dictionary.put(key, value);
}
public void remove(K key) throws BaseException {
if (!dictionary.containsKey(key)) {
throw new BaseException("Key does not exist in dictionary.");
}
dictionary.remove(key);
}
public V get(K key) throws BaseException {
if (!dictionary.containsKey(key)) {
throw new BaseException("Key does not exist in dictionary.");
}
return dictionary.get(key);
}
public boolean contains(K key) {
return dictionary.containsKey(key);
}
public String toString() {
var sb = new StringBuilder();
for (var key : dictionary.keySet()) {
sb.append(key);
sb.append(" --> ");
sb.append(dictionary.get(key));
sb.append("\n");
}
return sb.toString();
}
public Collection<V> getContent() {
return dictionary.values();
}
public IDictionary<K, V> copy() {
var newDictionary = new GenericDictionary<K, V>();
for (var key : dictionary.keySet()) {
newDictionary.dictionary.put(key, dictionary.get(key));
}
return newDictionary;
}
public Hashtable<K, V> getDictionary() {
return dictionary;
}
}

Some files were not shown because too many files have changed in this diff Show More