diff --git a/scores.csv b/scores.csv index 71c59b0dba547a3654af6140e251f6aaee7a1528..04008fa624119ca025fb3dd1127ea9e6e7e4b12a 100644 --- a/scores.csv +++ b/scores.csv @@ -1,3 +1,4 @@ BugBuster;264;EASY ClusterChampion;127;MEDIUM BugBuster;264;EASY +BugBuster;2640000;HARD diff --git a/src/main/java/lab/MyEdit.java b/src/main/java/lab/MyEdit.java new file mode 100644 index 0000000000000000000000000000000000000000..07b46a578c37fea172e98f2dcb3e3d94c6d08755 --- /dev/null +++ b/src/main/java/lab/MyEdit.java @@ -0,0 +1,13 @@ +package lab; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface MyEdit { + public boolean readOnly() default false; + public boolean visible() default true; +} diff --git a/src/main/java/lab/data/Score.java b/src/main/java/lab/data/Score.java index 2be798381f3f0f0634acc64df29fa574b38e4ee7..c4b003bd511d1233f05a04be66774ae74d68d5fe 100644 --- a/src/main/java/lab/data/Score.java +++ b/src/main/java/lab/data/Score.java @@ -8,6 +8,7 @@ import jakarta.persistence.Enumerated; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import lab.MyEdit; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.EqualsAndHashCode; @@ -30,13 +31,20 @@ public class Score { @Id @GeneratedValue(strategy = GenerationType.AUTO) + @MyEdit(visible = false) private Long id; + @MyEdit(readOnly = true) private String name; + @MyEdit private int points; @Enumerated(EnumType.STRING) + @MyEdit private Level level; - + public String getVirtual(){ + return "aaaa"; + } + public static Score generate() { return new Score(null, getRandomNick(), RANDOM.nextInt(50, 300), Level.values()[RANDOM.nextInt(Level.values().length)]); } diff --git a/src/main/java/lab/gui/EditController.java b/src/main/java/lab/gui/EditController.java index 2d386b3c6a0268c3f8b53ef38bf856223cb40bc8..815f2da8480b4642188a3c2e20715394b22a05c7 100644 --- a/src/main/java/lab/gui/EditController.java +++ b/src/main/java/lab/gui/EditController.java @@ -1,7 +1,14 @@ package lab.gui; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Map; +import java.util.ResourceBundle; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -14,6 +21,7 @@ import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.layout.GridPane; import javafx.stage.Stage; +import lab.MyEdit; import lab.data.Score; import lombok.Setter; @@ -50,7 +58,50 @@ public class EditController { @FXML void btnOkAction(ActionEvent event) { - //TODO: add code to read values from text fields + try { + BeanInfo beanInfo = Introspector.getBeanInfo(data.getClass()); + for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors()) { + try { + String name = propertyDescriptor.getName(); + Field field = data.getClass().getDeclaredField(name); + MyEdit myEdit = field.getAnnotation(MyEdit.class); + if(myEdit == null || !myEdit.visible() || myEdit.readOnly()) { + continue; + } + TextField textField = nameToTextField.get(name); + String stringValue = textField.getText(); + Object value = null; + if (propertyDescriptor.getPropertyType() == String.class) { + value = stringValue; + } else if (stringValue == null || stringValue.isBlank()) { + value = null; + } else if (propertyDescriptor.getPropertyType() == Integer.class + || propertyDescriptor.getPropertyType() == int.class) { + value = Integer.parseInt(stringValue); + } else if (propertyDescriptor.getPropertyType() == Long.class + || propertyDescriptor.getPropertyType() == long.class) { + value = Long.parseLong(stringValue); + } else if (propertyDescriptor.getPropertyType() == Double.class + || propertyDescriptor.getPropertyType() == double.class) { + value = Double.parseDouble(stringValue); + } else if (propertyDescriptor.getPropertyType().isEnum()) { + for (Object enumConstant : propertyDescriptor.getPropertyType().getEnumConstants()) { + if (enumConstant.toString().equalsIgnoreCase(stringValue)) { + value = enumConstant; + break; + } + } + } + if (propertyDescriptor.getWriteMethod() != null) { + propertyDescriptor.getWriteMethod().invoke(data, value); + } + } catch (NoSuchFieldException e) { + log.warn("property {} has no field", propertyDescriptor.getName()); + } + } + } catch (IntrospectionException | IllegalAccessException | InvocationTargetException e) { + log.error(e); + } gameController.updateData((Score)data); stage.hide(); @@ -71,7 +122,32 @@ public class EditController { log.info("data set {}", data); content.getChildren().clear(); - //TODO: code to detect properties and add rows to dialog + ResourceBundle msg = ResourceBundle.getBundle("msg"); + try { + BeanInfo beanInfo = Introspector.getBeanInfo(data.getClass()); + int row = 0; + for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors()) { + try { + Field field = data.getClass().getDeclaredField(propertyDescriptor.getName()); + MyEdit myEdit = field.getAnnotation(MyEdit.class); + if (myEdit == null) { + continue; + } + if (!myEdit.visible()) { + continue; + } + String name = propertyDescriptor.getName(); + Object value = propertyDescriptor.getReadMethod().invoke(data); + String localizedName = msg.getString(String.format("%s.%s", data.getClass().getSimpleName(), field.getName())); + addDialogRow(row, name, localizedName, value != null ? value.toString() : "", !myEdit.readOnly()); + row++; + } catch (NoSuchFieldException e) { + log.warn("property '{}' has no field in class '{}'", propertyDescriptor.getName(), data.getClass().getCanonicalName()); + } + } + } catch (IntrospectionException | InvocationTargetException | IllegalAccessException e) { + log.error(e); + } } private void addDialogRow(int rowNumber, String name, String descriptionName, String stringValue, diff --git a/src/main/resources/lab/gui/application.css b/src/main/resources/lab/gui/application.css index 7f0e980478ac54ba9285d55c081a99e94305ece5..b317217cccab60767843f4b7503af00c6f62d474 100644 --- a/src/main/resources/lab/gui/application.css +++ b/src/main/resources/lab/gui/application.css @@ -22,7 +22,7 @@ Label { -fx-background-color:RGB(0.0,0.0,100.0); } #menuPanel { - -fx-background-image:url("lochness-background.jpg"); + -fx-background-image:url("game-background.jpg"); -fx-background-size: stretch; } diff --git a/src/main/resources/lab/gui/game-background.jpg b/src/main/resources/lab/gui/game-background.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1875d2d18f49694c7e07858ffc4bf2eece5c1e39 Binary files /dev/null and b/src/main/resources/lab/gui/game-background.jpg differ diff --git a/src/main/resources/msg.properties b/src/main/resources/msg.properties new file mode 100644 index 0000000000000000000000000000000000000000..d0655f9afcee79b8fb8c5a4087d2d2b38292a47d --- /dev/null +++ b/src/main/resources/msg.properties @@ -0,0 +1,5 @@ + +Score.id = id +Score.level = level +Score.name = name +Score.points = points diff --git a/src/main/resources/msg_cs.properties b/src/main/resources/msg_cs.properties new file mode 100644 index 0000000000000000000000000000000000000000..e397613b223ead974bf36a1be69512c88c897149 --- /dev/null +++ b/src/main/resources/msg_cs.properties @@ -0,0 +1,5 @@ + +Score.id = Jednozna\u010Dn\u00FD identifik\u00E1tor +Score.level = Obt\u00ED\u017Enost +Score.name = Jm\u00E9no +Score.points = Body diff --git a/src/main/resources/msg_cs_CZ.properties b/src/main/resources/msg_cs_CZ.properties new file mode 100644 index 0000000000000000000000000000000000000000..73f926b653417019db394ae6ac1b0e5a9d5a56ae --- /dev/null +++ b/src/main/resources/msg_cs_CZ.properties @@ -0,0 +1,4 @@ +#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/) + +Score.id = Jedine\u010Dn\u00FD identifik\u00E1tor +Score.name = N\u00E1zev diff --git a/src/main/resources/msg_en.properties b/src/main/resources/msg_en.properties new file mode 100644 index 0000000000000000000000000000000000000000..83da6ab577a70580f3495e7d495641b54b61e490 --- /dev/null +++ b/src/main/resources/msg_en.properties @@ -0,0 +1,6 @@ +#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/) + +Score.id = Unique identificator +Score.level = Level +Score.name = Name +Score.points = Points diff --git a/src/test/java/jez04/structure/test/ClassStructureTest.java b/src/test/java/jez04/structure/test/ClassStructureTest.java index 710d8d2ea19892f30c4545f6abc453ac83eac19e..2e2be8bd0437f77356df9882a1e0553ec44d8a03 100644 --- a/src/test/java/jez04/structure/test/ClassStructureTest.java +++ b/src/test/java/jez04/structure/test/ClassStructureTest.java @@ -17,35 +17,24 @@ class ClassStructureTest { // @formatter:off @ParameterizedTest @CsvSource({ - "Bullet.java,serialVersionUID", - "Bullet.java,@Serial", - "BulletAnimated.java,serialVersionUID", - "BulletAnimated.java,@Serial", - "Cannon.java,serialVersionUID", - "Cannon.java,@Serial", - "Ufo.java,serialVersionUID", - "Ufo.java,@Serial", - "MyPoint.java,serialVersionUID", - "MyPoint.java,@Serial", - "WorldEntity.java,serialVersionUID", - "WorldEntity.java,@Serial", - - "WorldEntity.java,transient", - "BulletAnimated.java,transient", - - "World.java,new ServerSocket", - "World.java,Socket", - "World.java,accept", - "World.java,ObjectOutputStream", - "World.java,writeObject", - "World.java,new Socket", - "World.java,ObjectInputStream", - "World.java,ObjectInputStream", - "World.java,synchronized", + "Score.java,@MyEdit,4", + "EditController.java,Introspector.getBeanInfo,1", + "EditController.java,BeanInfo,1", + "EditController.java,PropertyDescriptor,1", + "EditController.java,getDeclaredField,1", + "EditController.java,getAnnotation,1", + "EditController.java,\\.readOnly\\(\\),1", + "EditController.java,\\.visible\\(\\),1", + "MyEdit.java,@interface,1", + "MyEdit.java,@Retention,1", + "MyEdit.java,RetentionPolicy\\.RUNTIME,1", + "MyEdit.java,readOnly\\(\\),1", + "MyEdit.java,visible\\(\\),1", + "msg(_.*)?\\.properties,points,2", }) // @formatter:on - void anotaceTest(String file, String annotation) throws URISyntaxException { - assertThat(TextFileContains.getProjectRoot(getClass()), new TextFileContains(file, annotation)); + void anotaceTest(String file, String annotation, int count) throws URISyntaxException { + assertThat(TextFileContains.getProjectRoot(getClass()), new TextFileContains(file, annotation).count(count).useRegExpForName(true)); }