diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..2fe0953 --- /dev/null +++ b/.classpath @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/demo/oskdemo.jar b/demo/oskdemo.jar new file mode 100644 index 0000000..0985e45 Binary files /dev/null and b/demo/oskdemo.jar differ diff --git a/demo/oskdemo.txt b/demo/oskdemo.txt new file mode 100644 index 0000000..7176bf5 --- /dev/null +++ b/demo/oskdemo.txt @@ -0,0 +1,5 @@ +IT Crowd +Dune +Game of Thrones +Princess Bride +Mars Attacks! diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..cb9e9ba --- /dev/null +++ b/pom.xml @@ -0,0 +1,29 @@ + + 4.0.0 + OSK + OSK + + UTF-8 + + 0.0.1-SNAPSHOT + + + junit + junit + 4.12 + + + + src + + + maven-compiler-plugin + 3.7.0 + + 1.8 + 1.8 + + + + + \ No newline at end of file diff --git a/src/main/java/osk/OnScreenKeyboardInstructionGenerator.java b/src/main/java/osk/OnScreenKeyboardInstructionGenerator.java new file mode 100644 index 0000000..e0fc17d --- /dev/null +++ b/src/main/java/osk/OnScreenKeyboardInstructionGenerator.java @@ -0,0 +1,40 @@ +package osk; + +import java.util.List; +import java.util.Scanner; +import utils.FileParser; +import utils.Translator; + +/** + * + * @author Aaron Reinard + * + * Generate OnScreen keyboard instructions for media titles in provided in flat file + * + */ + +public class OnScreenKeyboardInstructionGenerator { + + public static void main(String[] args) throws Exception { + + String file = null; + Scanner input = new Scanner(System.in); + + try { + System.out.print("Please enter file: "); + file = input.next(); + input.close(); + + List titleList = FileParser.parseFlatFile(file); + List keyboardInstructionList = Translator.getKeyboardInstructionStringList(titleList); + keyboardInstructionList.forEach(x -> System.out.println(x)); + + } catch (Exception e) { + throw new Exception( + "Unable to translate keyboard instructions for " + file + ". " + e.getMessage()); + } + } + + + +} diff --git a/src/main/java/screen/Coordinates.java b/src/main/java/screen/Coordinates.java new file mode 100644 index 0000000..234a64d --- /dev/null +++ b/src/main/java/screen/Coordinates.java @@ -0,0 +1,37 @@ +package screen; + +/** + * + * @author Aaron Reinard + * + * Contains coordinates used for keyboard navigation instructions + * + */ +public class Coordinates { + + private int x; + private int y; + + public Coordinates(int x, int y) { + this.x = x; + this.y = y; + + } + + public int getX() { + return x; + } + + public void setX(int value) { + this.x = value; + } + + public int getY() { + return y; + } + + public void setY(int value) { + this.y = value; + } + +} diff --git a/src/main/java/screen/Key.java b/src/main/java/screen/Key.java new file mode 100644 index 0000000..63619f5 --- /dev/null +++ b/src/main/java/screen/Key.java @@ -0,0 +1,34 @@ +package screen; + +/** + * + * @author Aaron Reinard + * + */ +public class Key { + + private String value; + private Coordinates coordinates; + + public Key(String character, Coordinates values) { + setValue(character); + setCoordinates(values); + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Coordinates getCoordinates() { + return coordinates; + } + + public void setCoordinates(Coordinates values) { + this.coordinates = values; + } + +} diff --git a/src/main/java/screen/Keyboard.java b/src/main/java/screen/Keyboard.java new file mode 100644 index 0000000..3151271 --- /dev/null +++ b/src/main/java/screen/Keyboard.java @@ -0,0 +1,62 @@ +package screen; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Aaron Reinard + * + * Keyboard dictionary containing keyset and coordinates + * + */ + +public class Keyboard { + + private List keys = null; + + public Keyboard() { + this.keys = setKeys(); + } + + public List getKeys() { + return keys; + } + + public Key getKey(String value) { + Key result = null; + for (Key keyMap : getKeys()) { + if (keyMap.getValue().equalsIgnoreCase(value)) { + result = keyMap; + break; + } + } + return result; + } + + + private List setKeys() { + + List keyList = new ArrayList(); + List lines = new ArrayList(); + + lines.add("ABCDEF"); + lines.add("GHIJKL"); + lines.add("MNOPQR"); + lines.add("STUVWX"); + lines.add("YZ1234"); + lines.add("567890"); + + int yInt = 0; + for (String line : lines) { + for (int xInt = 0; xInt < line.length(); xInt++) { + String value = String.valueOf(line.charAt(xInt)); + Coordinates coordinates = new Coordinates(xInt, yInt); + keyList.add(new Key(value, coordinates)); + } + yInt++; + } + return keyList; + } + +} diff --git a/src/main/java/utils/FileParser.java b/src/main/java/utils/FileParser.java new file mode 100644 index 0000000..5c22b4e --- /dev/null +++ b/src/main/java/utils/FileParser.java @@ -0,0 +1,43 @@ +package utils; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class FileParser { + + /** + * + * @param filePath inputFile + * @return list of strings parsed from flat file + * @throws IOException + */ + public static List parseFlatFile(String filePath) throws IOException { + List resultList = new ArrayList(); + try { + File input = new File(filePath); + InputStream inputStream = new FileInputStream(input); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + resultList = reader.lines().map(mapToString).collect(Collectors.toList()); + reader.close(); + } catch (Exception e) { + throw new IOException("unable to parse file " + filePath + "; " + e.getMessage()); + } + return resultList; + } + + private static Function mapToString = (line) -> { + String items[] = line.split("\\r?\\n"); + String item = items[0]; + return item; + + }; + +} diff --git a/src/main/java/utils/Translator.java b/src/main/java/utils/Translator.java new file mode 100644 index 0000000..a0eaa5f --- /dev/null +++ b/src/main/java/utils/Translator.java @@ -0,0 +1,185 @@ +package utils; + +import java.util.ArrayList; +import java.util.List; +import screen.Coordinates; +import screen.Keyboard; + +/** + * + * @author Aaron Reinard + * + * Used to convert strings and lists of string into on screen keyboard instructions. + * */ + +public class Translator { + + private static Keyboard keyboard = new Keyboard(); + + /** + * @return returns list of character string instructions for keyboard + * @throws Exception + */ + public static List getKeyboardInstructionStringList(List titles) + throws Exception { + List navigationList = new ArrayList(); + for (String title : titles) { + navigationList.add(getKeyboardInstructionString(title)); + } + return navigationList; + } + + /** + * + * @param title media title to be formatted into keyboard character instructions + * @return formatted keyboard character instructions + * @throws Exception + */ + public static String getKeyboardInstructionString(String title) throws Exception { + + // remove unsupported special characters + title = getFormattedTitle(title); + + String result = ""; + String startValue = "A"; + String endValue = ""; + + try { + for (int i = 0; i < title.length(); i++) { + endValue = String.valueOf(title.charAt(i)); + result += getSingleCharacterKeybordInstructions(startValue, endValue) + ","; + if (!endValue.equals(" ")) { + startValue = endValue; + } else { + endValue = startValue; + } + } + } catch (Exception e) { + throw new Exception("Unable to parse title " + e.getMessage()); + + } + return result.substring(0, result.length() - 1); + } + + /** + * creates a set of keyboard charater instructions to navigate between two keys + * + * @param startValue starting character + * @param endValue + * @return keyboard instructions to navigate between characters + * @throws Exception + */ + public static String getSingleCharacterKeybordInstructions(String startValue, String endValue) + throws Exception { + + String result = null; + + // if space, don't calculate coordinateDiff, just use 'S' + if (endValue.equals(" ")) { + result = "S"; + } else { + Coordinates startCoordinates = keyboard.getKey(startValue).getCoordinates(); + Coordinates endCoordinates = keyboard.getKey(endValue).getCoordinates(); + Coordinates coordinateDiff = getCoordinateDiff(startCoordinates, endCoordinates); + + String yNavigationString = getSingleCharacterYKeyboardInstructions(coordinateDiff.getY()); + String xNavigationString = getSingleCharacterXKeyboardInstructions(coordinateDiff.getX()); + result = yNavigationString + xNavigationString + "#"; + } + return result; + + } + + /** + * creates a horizontal set of keyboard instructions based on integer + * + * @param diff number of character movements required + * @return a horizontal set of keyboard instructions based on integer + * + */ + private static String getSingleCharacterXKeyboardInstructions(int diff) { + + String result = ""; + + for (int i = 0; i < Math.abs(diff); i++) { + result += getKeyboardInstructionCharacter(diff, "X"); + } + + return result; + + } + + /** + * creates a vertical set of keyboard instructions based on integer + * + * @param diff number of character movements required + * @return a horizontal set of keyboard instructions based on integer + * + */ + private static String getSingleCharacterYKeyboardInstructions(int diff) { + + String result = ""; + + for (int i = 0; i < Math.abs(diff); i++) { + result += getKeyboardInstructionCharacter(diff, "Y"); + } + + return result; + + } + + /** + * + * @param direction of navigation + * @param coordinateType X or Y axis + * @return character value required for keyboard instructions + */ + private static String getKeyboardInstructionCharacter(int diff, String coordinateType) { + + String plusValue = null; + String minusValue = null; + + if (coordinateType.equalsIgnoreCase("X")) { + plusValue = "L,"; + minusValue = "R,"; + } else { + plusValue = "U,"; + minusValue = "D,"; + } + + if (diff == 0) { + return ""; + } else if (diff < 0) { + return minusValue; + } else { + return plusValue; + } + + } + + /** + * + * @param title + * @return title with replaced non-alpha numeric characters + */ + public static String getFormattedTitle(String title) { + String result = title.replaceAll("[^A-Za-z0-9 ]", ""); + return result; + } + + /** + * + * @param startCoordinates starting key + * @param endCoordinates ending key + * @return difference in keyboard coordinates between two keys + */ + private static Coordinates getCoordinateDiff(Coordinates startCoordinates, + Coordinates endCoordinates) { + int xDiff = startCoordinates.getX() - endCoordinates.getX(); + int yDiff = startCoordinates.getY() - endCoordinates.getY(); + return new Coordinates(xDiff, yDiff); + } + + + +} diff --git a/src/test/java/utilstest/TestRunner.java b/src/test/java/utilstest/TestRunner.java new file mode 100644 index 0000000..bcd519d --- /dev/null +++ b/src/test/java/utilstest/TestRunner.java @@ -0,0 +1,14 @@ +package utilstest; + +import org.junit.runner.JUnitCore; +import org.junit.runner.Result; + +public class TestRunner { + public static void main(String[] args) { + System.out.println("Executing tests..."); + Result result = JUnitCore.runClasses(TranslatorTest.class); + result.getFailures().forEach(x -> System.out.println(x)); + System.out.println("Test execution complete!"); + } + +} diff --git a/src/test/java/utilstest/TranslatorTest.java b/src/test/java/utilstest/TranslatorTest.java new file mode 100644 index 0000000..5652725 --- /dev/null +++ b/src/test/java/utilstest/TranslatorTest.java @@ -0,0 +1,74 @@ +package utilstest; + +import static org.junit.Assert.assertEquals; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.OutputStream; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import utils.Translator; + +public class TranslatorTest { + + OutputStream stream; + + + @Before + public void initialize() { + try { + stream = new FileOutputStream(""); + } catch (FileNotFoundException e) { + } + } + + @After + public void cleanup() { + try { + if (stream != null) + stream.close(); + } catch (Exception e) { + + } + } + + @Test + public void test_translator_getKeyboardInstructionStringBaseline() { + + String translated = null; + try { + translated = Translator.getKeyboardInstructionString("IT Crowd"); + } catch (Exception e) { + } + + String expected = "D,R,R,#,D,D,L,#,S,U,U,U,R,#,D,D,R,R,R,#,L,L,L,#,D,R,R,#,U,U,U,L,#"; + assertEquals(expected, translated); + } + + @Test + public void test_translator_verifySpecialCharacterHandle() { + + String formatted = Translator.getFormattedTitle("~!@#$%1^&*()A<>?:2{}}|+"); + assertEquals("1A2", formatted); + + } + + @Test + public void test_translator_getSingleCharacterKeyboardInstructions() { + + String actual = null; + try { + actual = Translator.getSingleCharacterKeybordInstructions("A", "A"); + } catch (Exception e) { + } + assertEquals("#",actual); + + try { + actual = Translator.getSingleCharacterKeybordInstructions("M", "A"); + } catch (Exception e) { + } + assertEquals("U,U,#",actual); + + } + +}