Skip to content
Open

Queue #136

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 61 additions & 3 deletions src/main/java/hse/java/lectures/lecture3/tasks/atm/Atm.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,72 @@ public static Denomination fromInt(int value) {
public Atm() {
}

public void deposit(Map<Denomination, Integer> banknotes){}
public void deposit(Map<Denomination, Integer> banknotes) {
if (banknotes == null){
throw new InvalidDepositException("null");
}
int sum = 0;
for (var entry : banknotes.entrySet()) {
if (entry.getValue() < 0) {
throw new InvalidDepositException("Отрицательное денег");
}

sum += entry.getValue();
}
if (sum == 0) {
throw new InvalidDepositException("Ноль денег");
}
for (var entry : banknotes.entrySet()) {
this.banknotes.merge(entry.getKey(), entry.getValue(), Integer::sum);
}
}

public Map<Denomination, Integer> withdraw(int amount) {
return Map.of();
if (amount <= 0) {
throw new InvalidAmountException("<=0 денег");
} else if (amount % 50 != 0) {
throw new CannotDispenseException("Че ты у меня просишь");
}
if (amount > getBalance()){
throw new InsufficientFundsException("нет столько денег");
}

Map<Denomination, Integer> result = new EnumMap<>(Denomination.class);
int remaining = amount;

Denomination[] denominations = Denomination.values();
for (int i = denominations.length - 1; i >= 0; i--) {
Denomination denom = denominations[i];
int available = banknotes.getOrDefault(denom, 0);
if (available > 0 && denom.value() <= remaining) {
int needed = remaining / denom.value();
int toTake = Math.min(needed, available);

if (toTake > 0) {
result.put(denom, toTake);
remaining -= toTake * denom.value();
}
}
}

if (remaining != 0) {
throw new CannotDispenseException("Невозможно выдать сумму");
}

for (var entry : result.entrySet()) {
banknotes.merge(entry.getKey(), entry.getValue(),
(oldVal, newVal) -> oldVal - newVal);
}

return result;
}

public int getBalance() {
return 0;
int balance = 0;
for (var entry : banknotes.entrySet()) {
balance += entry.getKey().value() * entry.getValue();
}
return balance;
}

}
120 changes: 116 additions & 4 deletions src/main/java/hse/java/lectures/lecture3/tasks/html/HtmlDocument.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Set;
import java.util.*;

public class HtmlDocument {

private static final Set<String> SUPPORTED_TAGS = Set.of("html", "head", "body", "div", "p");

public HtmlDocument(String filePath) {
this(Path.of(filePath));
}
Expand All @@ -27,6 +27,118 @@ private String readFile(Path filePath) {
}
}

private void validate(String content){}
private void validate(String content) {
ArrayList<String> tagStack = new ArrayList<>();
int position = 0;
boolean hasHtmlTag = false;
boolean hasHeadTag = false;
boolean hasBodyTag = false;
boolean headFinished = false;

while (position < content.length()) {
if (content.charAt(position) != '<') {
position++;
continue;
}

int tagStart = position;
int tagEnd = content.indexOf('>', tagStart);

if (tagEnd == -1) {
throw new InvalidStructureException("Unclosed tag bracket at position " + tagStart);
}

String tagContent = content.substring(tagStart + 1, tagEnd).trim();
position = tagEnd + 1;

boolean isClosingTag = false;
if (tagContent.startsWith("/")) {
isClosingTag = true;
tagContent = tagContent.substring(1).trim();
}

String tagName = extractTagName(tagContent);

if (isClosingTag) {
handleClosingTag(tagName, tagStack);

if (tagName.equals("head")) {
headFinished = true;
}
} else {
handleOpeningTag(tagName, tagStack);
switch (tagName) {
case "html" -> {
if (hasHtmlTag || tagStack.size()!= 1) {
throw new InvalidStructureException("html");
}
hasHtmlTag = true;
}
case "head" -> {
if (hasHeadTag || hasBodyTag || !hasHtmlTag) {
throw new InvalidStructureException("head");
}
hasHeadTag = true;
}
case "body" -> {
if (hasBodyTag || !hasHtmlTag || hasHeadTag && !headFinished) {
throw new InvalidStructureException("body");
}

hasBodyTag = true;
}
default -> {
if (!(hasBodyTag || hasHeadTag)){
throw new InvalidStructureException("дефолт");
}
}
}

}
}

if (!tagStack.isEmpty()) {
throw new UnclosedTagException("Незакрытый тег");
}

if (!hasHtmlTag) {
throw new InvalidStructureException("Нет html");
}
}

private String extractTagName(String tagContent) {
int spaceIndex = tagContent.indexOf(' ');
if (spaceIndex != -1) {
return tagContent.substring(0, spaceIndex).toLowerCase();
}
return tagContent.toLowerCase();
}

private void checkSupport(String tagName) {
if (!SUPPORTED_TAGS.contains(tagName)) {
throw new UnsupportedTagException("Тег фигня");
}
}

private void handleOpeningTag(String tagName, ArrayList<String> tagStack) {
checkSupport(tagName);
tagStack.add(tagName);
}

private void handleClosingTag(String tagName, ArrayList<String> tagStack) {
checkSupport(tagName);

if (tagStack.isEmpty()) {
throw new UnexpectedClosingTagException("Хочу закрыть а нет открытых");
}

String lastOpenedTag = tagStack.get(tagStack.size() - 1);

if (!lastOpenedTag.equals(tagName)) {
throw new MismatchedClosingTagException("Хочу закрыть а там не тот");
}

tagStack.remove(tagStack.size() - 1);
}

}
Original file line number Diff line number Diff line change
@@ -1,25 +1,46 @@
package hse.java.lectures.lecture6.tasks.queue;

import java.util.LinkedList;
import java.util.Queue;

public class BoundedBlockingQueue<T> {

private final Queue<T> queue;
private final int cap;

public BoundedBlockingQueue(int capacity) {

if (capacity <= 0) {
throw new IllegalArgumentException("capacity must be > 0");
}
this.cap = capacity;
this.queue = new LinkedList<>();
}

public void put(T item) throws InterruptedException {

public synchronized void put(T item) throws InterruptedException {
if (item == null) {
throw new NullPointerException("null is not allowed");
}
while (queue.size() == cap) {
wait();
}
queue.add(item);
notifyAll();
}

public T take() throws InterruptedException {
return null;
public synchronized T take() throws InterruptedException {
while (queue.isEmpty()) {
wait();
}
T item = queue.poll();
notifyAll();
return item;
}

public int size() {
return 0;
public synchronized int size() {
return queue.size();
}

public int capacity() {
return 0;
return cap;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,14 @@ public void attachMonitor(StreamingMonitor monitor) {
public void run() {
// Writer threads are intentionally infinite for the task contract.
while (true) {
if (!monitor.awaitTurn(id)) {
return;
}

output.print(message);
onTick.run();

monitor.tickDone();
}
}

}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,60 @@
package hse.java.lectures.lecture6.tasks.synchronizer;

import java.util.List;

public class StreamingMonitor {
// impl your sync here
}
private final List<Integer> sortedIds;
private int currentIndex;

private int totalTicksDone;
private final int totalTicksRequired;

private boolean finished;

public StreamingMonitor(List<Integer> sortedIds, int ticksPerWriter) {
this.sortedIds = sortedIds;
this.currentIndex = 0;
this.totalTicksRequired = sortedIds.size() * ticksPerWriter;
this.totalTicksDone = 0;
this.finished = false;
}

private int currentId() {
return sortedIds.get(currentIndex);
}

public synchronized boolean awaitTurn(int writerId) {
while (currentId() != writerId && !finished) {
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
return !finished;
}

public synchronized void tickDone() {
totalTicksDone++;

currentIndex = (currentIndex + 1) % sortedIds.size();

if (totalTicksDone >= totalTicksRequired) {
finished = true;
}

notifyAll();
}

public synchronized void awaitFinished() {
while (!finished) {
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package hse.java.lectures.lecture6.tasks.synchronizer;

import java.util.List;
import java.util.stream.Collectors;

public class Synchronizer {

Expand All @@ -22,12 +23,23 @@ public Synchronizer(List<StreamWriter> tasks, int ticksPerWriter) {
* in strict ascending id order.
*/
public void execute() {
// add monitor and sync
List<Integer> sortedIds = tasks.stream()
.map(StreamWriter::getId)
.sorted()
.collect(Collectors.toList());

StreamingMonitor monitor = new StreamingMonitor(sortedIds, ticksPerWriter);

for (StreamWriter writer : tasks) {
writer.attachMonitor(monitor);
}

for (StreamWriter writer : tasks) {
Thread worker = new Thread(writer, "stream-writer-" + writer.getId());
worker.setDaemon(true);
worker.start();
}
}

}
monitor.awaitFinished();
}
}
Loading