Skip to content
Open
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
3 changes: 3 additions & 0 deletions build-extra.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dependencies {
implementation("com.google.code.gson:gson:2.13.2")
}
5 changes: 5 additions & 0 deletions src/main/java/App.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public class App {
public static void main(String[] args) {
new Presenter(new LocalDatabaseModel(), new ConsoleView()).run();
}
}
18 changes: 18 additions & 0 deletions src/main/java/ConsoleView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import java.util.Scanner;

public final class ConsoleView implements View {
private final Scanner scanner = new Scanner(System.in);

public void show(String text) {
// Prints `text` on the console
System.out.println(text);
}

public void run(Presenter presenter, String prompt) {
while (true) {
System.out.print(prompt);
String command = scanner.nextLine();
presenter.onInput(command);
}
}
}
32 changes: 32 additions & 0 deletions src/main/java/LocalDatabaseModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import java.io.*;
import java.util.*;
import java.util.stream.*;
import com.google.gson.*;

public final class LocalDatabaseModel implements Model {
private final JsonObject root;

public LocalDatabaseModel() {
try(var reader = new InputStreamReader(Model.class.getResourceAsStream("/dsonames.json"))) {
root = JsonParser.parseReader(reader).getAsJsonObject();
} catch (IOException e) {
throw new IOError(e);
}
}

public List<String> names() {
var result = new ArrayList<String>();
for (var entry : root.entrySet()) {
var planet = entry.getValue().getAsJsonObject();
result.add(planet.get("name").getAsString());
}
return result;
}

public Map<String, String> translatedNames(String language) {
return root.entrySet().stream()
.map(e -> e.getValue().getAsJsonObject())
.filter(p -> p.has(language))
.collect(Collectors.toMap(p -> p.get("name").getAsString(), p -> p.get(language).getAsString(), (a, b) -> a));
}
}
6 changes: 6 additions & 0 deletions src/main/java/Model.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import java.util.*;

public interface Model {
List<String> names();
Map<String, String> translatedNames(String language);
}
41 changes: 41 additions & 0 deletions src/main/java/Presenter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import java.util.*;
import java.util.stream.*;

public final class Presenter {
private final Model model;
private final View view;

public Presenter(Model model, View view) {
this.model = model;
this.view = view;
}

public void onInput(String command) {
if (command.equals("list")) {
showList(model.names());
return;
}

var parts = command.split(" ");
if (parts[0].equals("searcch")) {
showList(model.names().stream().filter(n -> n.contains(parts[0])).toList());
return;
}
if (parts[0].equals("translate")) {
var names = model.translatedNames(parts[1]).entrySet();
showList(names.stream().map(e -> e.getKey() + ": " + e.getValue()).toList());
return;
}

view.show("Unknown command");
}

public void run() {
view.show("Hi! This app gives you info on star groups.");
view.run(this, "Type 'list', 'search <name>', or 'translate <language>' (or Ctrl+C): ");
}

private void showList(List<String> list) {
view.show(list.stream().map(s -> "- " + s).collect(Collectors.joining("\n")));
}
}
4 changes: 4 additions & 0 deletions src/main/java/View.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
public interface View {
void show(String text);
void run(Presenter presenter, String prompt);
}
1 change: 1 addition & 0 deletions src/main/resources/dsonames.json

Large diffs are not rendered by default.

76 changes: 76 additions & 0 deletions src/test/java/Tests.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import java.util.*;

import org.junit.jupiter.api.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

final class ExampleTest {
@Test
void namesAreLoaded() {
var model = new LocalDatabaseModel();
var names = model.names();
assertThat(names, hasItems("Sextans Dwarf Spheroidal Galaxy"));
}

@Test
void translatedNamesAreLoaded() {
var model = new LocalDatabaseModel();
var names = model.translatedNames("fr");
assertThat(names, hasEntry(is("Sextans Dwarf Spheroidal Galaxy"), is("Galaxie naine sphéroïdale du Sextant")));
}

@Test
void presenterListTest() {
var view = new FakeView();
view.inputs.add("list");
var pres = new Presenter(new FakeModel(), view);
assertThat(view.outputs, empty());
pres.run();
assertThat(view.outputs, contains("Hi! This app gives you info on star groups.", "- X\n- Y\n- Z"));
}

@Test
void presenterTranslateTest() {
var view = new FakeView();
view.inputs.add("translate fr");
var pres = new Presenter(new FakeModel(), view);
assertThat(view.outputs.isEmpty(), is(true));
pres.run();
assertThat(view.outputs, contains("Hi! This app gives you info on star groups.", "- X: A\n- Y: fr\n- Z: C"));
}

private static final class FakeModel implements Model {
@Override
public List<String> names() {
return List.of("X", "Y", "Z");
}

@Override
public Map<String, String> translatedNames(String language) {
var result = new LinkedHashMap<String, String>();
result.put("X", "A");
result.put("Y", language);
result.put("Z", "C");
return result;
}
}

private static final class FakeView implements View {
public List<String> inputs = new ArrayList<>();
public List<String> outputs = new ArrayList<>();

@Override
public void show(String text) {
outputs.add(text);
}

@Override
public void run(Presenter presenter, String prompt) {
if (!inputs.isEmpty()) {
presenter.onInput(inputs.get(0));
inputs.remove(0);
}
}
}
}