[LIB-9] merge to graphics: Set of entities for PGN parsing and formatting
authorgotty <gotty@hedgecode.org>
Sat, 25 Jan 2020 00:21:58 +0000 (03:21 +0300)
committergotty <gotty@hedgecode.org>
Sat, 25 Jan 2020 00:21:58 +0000 (03:21 +0300)
63 files changed:
.gitignore [new file with mode: 0644]
CHANGELOG [new file with mode: 0644]
LICENSE [new file with mode: 0644]
NOTICE [new file with mode: 0644]
README.md [new file with mode: 0644]
chesshog-core/pom.xml
chesshog-core/src/main/java/org/hedgecode/chess/ChessHogApp.java
chesshog-core/src/main/java/org/hedgecode/chess/ChessHogConsole.java [new file with mode: 0644]
chesshog-core/src/main/java/org/hedgecode/chess/ChessHogProperties.java [new file with mode: 0644]
chesshog-core/src/main/resources/chesshog.properties [new file with mode: 0644]
chesshog-dbetude/pom.xml
chesshog-dbetude/src/test/groovy/org/hedgecode/chess/db/CreateDBTest.groovy [new file with mode: 0644]
chesshog-format/pom.xml
chesshog-format/src/main/java/org/hedgecode/chess/img/AbstractImageLoader.java [deleted file]
chesshog-format/src/main/java/org/hedgecode/chess/img/board/BoardLoader.java [deleted file]
chesshog-graphics/pom.xml [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/AbstractImageLoader.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/Diagram.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/DiagramBuilder.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/DiagramBuilder.java with 85% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/FilenameUtils.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageBuilder.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/ImageException.java with 73% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageConstants.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/ImageConstants.java with 89% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageException.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageFilter.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/ImageFilter.java with 65% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageFormat.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/ImageFormat.java with 72% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageFormatShaper.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageLoader.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/ImageLoader.java with 96% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageShaper.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/bitmap/BitmapImageShaper.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/board/Board.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/board/Board.java with 78% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/board/BoardLoader.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/board/SquarePair.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/board/SquarePair.java with 86% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/DefFileSystemContractor.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/FileSystemContractor.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/FileSystemDetector.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/JarFileSystemContractor.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/piece/PieceSet.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/piece/PieceSet.java with 96% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/piece/PieceSetLoader.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/piece/PieceSetLoader.java with 59% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/vector/SquareImageTranscoder.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/vector/VectorImageShaper.java [new file with mode: 0644]
chesshog-graphics/src/main/resources/org/hedgecode/chess/img/LocalStrings.properties [new file with mode: 0644]
chesshog-graphics/src/main/resources/org/hedgecode/chess/img/LocalStrings_ru.properties [new file with mode: 0644]
chesshog-hedgefish/pom.xml
chesshog-qrcode/pom.xml
chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/ChessQRCodeApp.java [new file with mode: 0644]
chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/ChessQRCodeConstants.java [moved from chesshog-qrcode/src/main/java/org/hedgecode/chess/ChessQRCodeConstants.java with 90% similarity]
chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/ChessQRCodeException.java
chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/ChessQRCodeMode.java
chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/ChessQRCodeReader.java
chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/ChessQRCodeWriter.java
chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/ChessQRMatrixUtils.java
chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/ChessQRResult.java
chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/zip/ZipChessQRCodeReader.java [new file with mode: 0644]
chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/zip/ZipChessQRCodeWriter.java [new file with mode: 0644]
chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/zip/ZipContentDeflater.java [new file with mode: 0644]
chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/zip/ZipContentInflater.java [new file with mode: 0644]
chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/zip/ZipContentUtils.java [new file with mode: 0644]
chesshog-qrcode/src/main/resources/org/hedgecode/chess/qrcode/LocalStrings.properties
chesshog-qrcode/src/main/resources/org/hedgecode/chess/qrcode/LocalStrings_ru.properties
chesshog-qrcode/src/test/java/org/hedgecode/chess/qrcode/ChessQRCodeReaderTest.java [moved from chesshog-qrcode/src/main/java/org/hedgecode/chess/ChessQRCodeApp.java with 67% similarity]
chesshog-qrcode/src/test/java/org/hedgecode/chess/qrcode/ChessQRCodeWriterTest.java [new file with mode: 0644]
chesshog-uci/pom.xml
pom.xml

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..2e28d95
--- /dev/null
@@ -0,0 +1,11 @@
+.project
+.classpath
+.settings/
+.svn/
+target/
+bin/
+out/
+*.ipr
+*.iml
+.idea
+.java-version
diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644 (file)
index 0000000..c2fdf49
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,7 @@
+CHANGELOG Hedgecode ChessHog
+============================
+
+v.0.1 [2020-XX-XX]
+------------------
+- Initial release of the project
+- ...
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..0954fe0
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,193 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+***************************************************************************
+
+   Copyright (c) 2018-2020 Hedgecode. All rights reserved.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/NOTICE b/NOTICE
new file mode 100644 (file)
index 0000000..b5b2dad
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,6 @@
+
+Hedgecode ChessHog
+Copyright (c) 2018-2020 Hedgecode. All rights reserved.
+
+This product includes software developed at
+Hedgecode (https://hedgecode.org/).
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..7b96133
--- /dev/null
+++ b/README.md
@@ -0,0 +1,25 @@
+## Hedgecode ChessHog
+
+### Description
+
+Hedgecode ChessHog is a chess project that includes modules with different functionality, such as:
+
+* own internal format for the presentation of chess games and positions, which makes
+  it possible to use this project as API library for various chess Java applications;
+* ability to work with various formats of chess games and diagrams (e.g. PGN, FEN),
+  including the functionality of generating chess positions in ASCII format,
+  as well as Wikipedia format;
+* provide full functionality for working with UCI (Universal Chess Interface) protocol,
+  which allows both connecting external UCI engines and developing your own
+  using API of UCI module with a set of necessary interfaces described in it;
+* building chess diagrams in the form of images with a diverse set of chess pieces;
+* ability to record chess games and positions in the form of a QR code,
+  as well as recognition of this chess QR code.
+
+### Links
+
+Below are links to the project description pages:
+- [ENG](https://lib.hedgecode.org/chesshog/)
+- [RUS](https://lib.hedgecode.org/chesshog/ru/)
+
+Copyright © 2018–2020 [Hedgecode](https://hedgecode.org/).
index d1dda9e..f200eef 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-  ~ Copyright (c) 2018. Developed by Hedgecode.
+  ~ Copyright (c) 2018-2019. Developed by Hedgecode.
   ~
   ~ Licensed under the Apache License, Version 2.0 (the "License");
   ~ you may not use this file except in compliance with the License.
index 94dfaa0..0a4f3dc 100644 (file)
@@ -25,6 +25,7 @@ public final class ChessHogApp {
 
     public static void main(String[] args) {
 
+        ChessHogConsole.init();
 
     }
 
diff --git a/chesshog-core/src/main/java/org/hedgecode/chess/ChessHogConsole.java b/chesshog-core/src/main/java/org/hedgecode/chess/ChessHogConsole.java
new file mode 100644 (file)
index 0000000..52a2802
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess;
+
+import java.time.LocalDateTime;
+import java.util.Calendar;
+
+/**
+ * ChessHog utility class for working with console.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class ChessHogConsole {
+
+    private static final String[] ASCII_LOGO = {
+            "  _______     _                   _                  ",
+            " |   |  _|_ _| |___ ___ ___ ___ _| |___              ",
+            " |     | -_| . | . | -_|  _| . | . | -_|             ",
+            " |     |___|___|_  |___|___|___|___|___|             ",
+            " |___|___|     |___|    _               _            ",
+            "                    ___| |_ ___ ___ ___| |_ ___ ___  ",
+            "                   |  _|   | -_|_ -|_ -|   | . | . | ",
+            "                   |___|_|_|___|___|___|_|_|___|_  | ",
+            "                                               |___| "
+    };
+
+    private static final String COPYRIGHT = "Copyright (c) Hedgecode";
+
+    private static boolean logMode = false;
+
+    private ChessHogConsole() {
+    }
+
+    public static void setLogMode(boolean isLogMode) {
+        logMode = isLogMode;
+    }
+
+    public static void console(String message) {
+        System.out.println(
+                String.format(
+                        logMode ? "[%1$tT] %2$s" : "%2$s",
+                        LocalDateTime.now(),
+                        message == null ? "" : message
+                )
+        );
+    }
+
+    public static void empty() {
+        console(null);
+    }
+
+    public static void init() {
+        asciiLogo();
+        copyright();
+        version();
+        empty();
+        os();
+        java();
+    }
+
+    private static void asciiLogo() {
+        for (String line : ASCII_LOGO) {
+            console(line);
+        }
+    }
+
+    private static void copyright() {
+        int inceptionYear = Integer.parseInt(
+                ChessHogProperties.get("chesshog.inception.year")
+        );
+        int currentYear = Calendar.getInstance().get(Calendar.YEAR);
+        String copyright = currentYear > inceptionYear
+                ? String.format("%s-%s %s", inceptionYear, currentYear, COPYRIGHT)
+                : String.format("%s %s", currentYear, COPYRIGHT);
+        console(
+                alignCenter(copyright)
+        );
+    }
+
+    private static void version() {
+        console(
+                alignCenter(
+                        String.format(
+                                "v. %s", ChessHogProperties.get("chesshog.version")
+                        )
+                )
+        );
+    }
+
+    private static void os() {
+        console(
+                String.format(
+                        "OS: %s %s %s",
+                        System.getProperty("os.name"),
+                        System.getProperty("os.version"),
+                        System.getProperty("os.arch")
+                )
+        );
+    }
+
+    private static void java() {
+        console(
+                String.format(
+                        "JRE: %s %s",
+                        System.getProperty("java.runtime.name"),
+                        System.getProperty("java.runtime.version")
+                )
+        );
+        console(
+                String.format(
+                        "JVM: %s %s %s",
+                        System.getProperty("java.vm.vendor"),
+                        System.getProperty("java.vm.name"),
+                        System.getProperty("java.vm.version")
+                )
+        );
+    }
+
+    private static String alignCenter(String message) {
+        int indent = (ASCII_LOGO[0].length() + message.length()) / 2;
+        return String.format(
+                "%" + indent + "s",
+                message
+        );
+    }
+
+}
diff --git a/chesshog-core/src/main/java/org/hedgecode/chess/ChessHogProperties.java b/chesshog-core/src/main/java/org/hedgecode/chess/ChessHogProperties.java
new file mode 100644 (file)
index 0000000..0642890
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * ChessHog properties holder.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class ChessHogProperties {
+
+    /** Properties file. */
+    private static final String PROPERTIES_FILE = "chesshog.properties";
+
+    /** Properties. */
+    private static final Properties PROPERTIES;
+
+    /**
+     * Static properties initialization.
+     */
+    static {
+        PROPERTIES = new Properties();
+        readProperties(PROPERTIES_FILE, PROPERTIES, true);
+    }
+
+    /**
+     * @param propsFile Properties file name.
+     * @param props Properties.
+     * @param throwExc Flag indicating whether to throw an exception or not.
+     */
+    public static void readProperties(String propsFile, Properties props, boolean throwExc) {
+        try (InputStream is = ChessHogProperties.class.getClassLoader().getResourceAsStream(propsFile)) {
+            if (is == null) {
+                if (throwExc)
+                    throw new RuntimeException("Failed to find properties file: " + propsFile);
+                else
+                    return;
+            }
+
+            props.load(is);
+        }
+        catch (IOException e) {
+            throw new RuntimeException("Failed to read properties file: " + propsFile, e);
+        }
+    }
+
+    /**
+     * Empty string for not found properties.
+     */
+    private static final String EMPTY = "";
+
+    /**
+     * Gets property value.
+     *
+     * @param key Property key.
+     * @return Property value (possibly empty string, but never {@code null}).
+     */
+    public static String get(String key) {
+        return PROPERTIES.getProperty(key, EMPTY);
+    }
+
+    /**
+     * Private constructor.
+     */
+    private ChessHogProperties() {
+    }
+
+}
diff --git a/chesshog-core/src/main/resources/chesshog.properties b/chesshog-core/src/main/resources/chesshog.properties
new file mode 100644 (file)
index 0000000..b5152fc
--- /dev/null
@@ -0,0 +1,18 @@
+# Copyright (c) 2018-2019. Developed by Hedgecode.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+chesshog.version=0.1-SNAPSHOT
+chesshog.build=0
+chesshog.revision=DEV
+chesshog.inception.year=2018
index 8a9e3f0..bbf054e 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-  ~ Copyright (c) 2018. Developed by Hedgecode.
+  ~ Copyright (c) 2018-2019. Developed by Hedgecode.
   ~
   ~ Licensed under the Apache License, Version 2.0 (the "License");
   ~ you may not use this file except in compliance with the License.
     <version>0.1-SNAPSHOT</version>
     <packaging>jar</packaging>
 
-    <name>Hedgecode ChessHog DB Engine Module</name>
+    <name>Hedgecode ChessHog DB Etude</name>
     <description>
-        Hedgecode ChessHog DB Engine Module.
+        Hedgecode ChessHog DB Etude Module.
     </description>
 
     <properties>
-        <chessHogVersion>0.1-SNAPSHOT</chessHogVersion>
         <hibernateCoreVersion>5.3.7.Final</hibernateCoreVersion>
         <hibernateJpaApiVersion>1.0.1.Final</hibernateJpaApiVersion>
         <mysqlVersion>8.0.13</mysqlVersion>
     <dependencies>
         <dependency>
             <groupId>org.hedgecode.chess</groupId>
-            <artifactId>chesshog</artifactId>
-            <version>${chessHogVersion}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.hedgecode.chess</groupId>
             <artifactId>chesshog-core</artifactId>
             <version>${chessHogVersion}</version>
         </dependency>
diff --git a/chesshog-dbetude/src/test/groovy/org/hedgecode/chess/db/CreateDBTest.groovy b/chesshog-dbetude/src/test/groovy/org/hedgecode/chess/db/CreateDBTest.groovy
new file mode 100644 (file)
index 0000000..d5204db
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.db
+
+/**
+ *
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+
+import javax.persistence.Persistence
+
+def factory = Persistence.createEntityManagerFactory("db-etude-persistence-unit")
+def manager = factory.createEntityManager()
+
+manager.getTransaction().begin()
+
+//manager.persist new ServerNode(firstName: "Test", lastName: "Server")
+
+manager.getTransaction().commit()
\ No newline at end of file
index 86a1a3f..784b9d2 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-  ~ Copyright (c) 2018. Developed by Hedgecode.
+  ~ Copyright (c) 2018-2019. Developed by Hedgecode.
   ~
   ~ Licensed under the Apache License, Version 2.0 (the "License");
   ~ you may not use this file except in compliance with the License.
         Hedgecode ChessHog Format Module.
     </description>
 
-    <properties>
-        <chessHogVersion>0.1-SNAPSHOT</chessHogVersion>
-    </properties>
-
     <dependencies>
         <dependency>
             <groupId>org.hedgecode.chess</groupId>
-            <artifactId>chesshog</artifactId>
-            <version>${chessHogVersion}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.hedgecode.chess</groupId>
             <artifactId>chesshog-core</artifactId>
             <version>${chessHogVersion}</version>
         </dependency>
diff --git a/chesshog-format/src/main/java/org/hedgecode/chess/img/AbstractImageLoader.java b/chesshog-format/src/main/java/org/hedgecode/chess/img/AbstractImageLoader.java
deleted file mode 100644 (file)
index 4bed015..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2018-2019. Developed by Hedgecode.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.hedgecode.chess.img;
-
-import java.io.File;
-
-/**
- *
- *
- * @author Dmitry Samoshin aka gotty
- */
-public abstract class AbstractImageLoader implements ImageLoader {
-
-    protected static final File IMAGES_PATH = new File(
-            ImageLoader.class.getResource(
-                    ImageConstants.RESOURCE_ROOT_DIR + ImageConstants.RESOURCE_IMAGES_DIR
-            ).getPath()
-    );
-
-    private Type loadType;
-
-    public AbstractImageLoader() {
-        this.loadType = Type.STATELESS;
-    }
-
-    protected abstract void clear();
-
-    @Override
-    public Type loadType() {
-        return loadType;
-    }
-
-    protected void setLoadType(Type loadType) {
-        if (Type.STATELESS.equals(loadType)) {
-            clear();
-        }
-        this.loadType = loadType;
-    }
-
-}
diff --git a/chesshog-format/src/main/java/org/hedgecode/chess/img/board/BoardLoader.java b/chesshog-format/src/main/java/org/hedgecode/chess/img/board/BoardLoader.java
deleted file mode 100644 (file)
index 4c2c18d..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2018-2019. Developed by Hedgecode.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.hedgecode.chess.img.board;
-
-import java.awt.image.BufferedImage;
-import java.io.File;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.imageio.ImageIO;
-
-import org.hedgecode.chess.img.AbstractImageLoader;
-import org.hedgecode.chess.img.ImageConstants;
-import org.hedgecode.chess.img.ImageException;
-import org.hedgecode.chess.img.ImageFilter;
-
-/**
- *
- *
- * @author Dmitry Samoshin aka gotty
- */
-public class BoardLoader extends AbstractImageLoader {
-
-    private static final File SQUARES_PATH = new File(IMAGES_PATH, ImageConstants.RESOURCE_SQUARES_DIR);
-
-    private static final String SQUARE_DARK = ImageConstants.DARK_SQUARE_FILENAME;
-    private static final String SQUARE_LIGHT = ImageConstants.LIGHT_SQUARE_FILENAME;
-
-    private static final String[] SQUARE_NAMES = {SQUARE_DARK, SQUARE_LIGHT};
-
-    private Map<String, Board> squareSetMap = new HashMap<>();
-
-    @Override
-    public Board load(String name) throws ImageException {
-        Board board = null;
-        SquarePair<BufferedImage> squarePair = null;
-        if (Type.STATELESS.equals(loadType()) || !squareSetMap.containsKey(name)) {
-            File boardPath = new File(SQUARES_PATH, name);
-            if (boardPath.exists() && boardPath.isDirectory()) {
-                squarePair = loadSquares(name, boardPath);
-            }
-            if (squarePair != null) {
-                board = Board.create(squarePair);
-                if (Type.STATEFUL.equals(loadType())) {
-                    squareSetMap.put(name, board);
-                }
-            }
-        } else {
-            board = squareSetMap.get(name);
-        }
-        return board;
-    }
-
-    @Override
-    public void unload(String name) {
-        if (Type.STATEFUL.equals(loadType()) && squareSetMap.containsKey(name)) {
-            squareSetMap.remove(name);
-        }
-    }
-
-    @Override
-    protected void clear() {
-        squareSetMap.clear();
-    }
-
-    private SquarePair<BufferedImage> loadSquares(String name, File boardPath) throws ImageException {
-        BufferedImage dark = null, light = null;
-        File[] images = boardPath.listFiles(new ImageFilter(SQUARE_NAMES));
-        if (images != null) {
-            for (File image : images) {
-                if (image.isFile()) {
-                    String filename = image.getName();
-                    try {
-                        switch (filename.substring(0, filename.lastIndexOf('.'))) {
-                            case SQUARE_DARK:
-                                dark = ImageIO.read(image);
-                                break;
-                            case SQUARE_LIGHT:
-                                light = ImageIO.read(image);
-                                break;
-                        }
-                    } catch (IOException e) {
-                        throw new ImageException(e.getMessage());  // todo: locale
-                    }
-                }
-            }
-        }
-        return (dark != null && light != null) ? SquarePair.create(dark, light) : null;
-    }
-
-}
diff --git a/chesshog-graphics/pom.xml b/chesshog-graphics/pom.xml
new file mode 100644 (file)
index 0000000..333741c
--- /dev/null
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ Copyright (c) 2018-2019. Developed by Hedgecode.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<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/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.hedgecode.chess</groupId>
+        <artifactId>chesshog</artifactId>
+        <version>0.1-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>chesshog-graphics</artifactId>
+    <version>0.1-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>Hedgecode ChessHog Graphics</name>
+    <description>
+        Hedgecode ChessHog Graphics Module.
+    </description>
+
+    <properties>
+        <transcoderVersion>1.11</transcoderVersion>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.hedgecode.chess</groupId>
+            <artifactId>chesshog-core</artifactId>
+            <version>${chessHogVersion}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.hedgecode.chess</groupId>
+            <artifactId>chesshog-format</artifactId>
+            <version>${chessHogVersion}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.xmlgraphics</groupId>
+            <artifactId>batik-transcoder</artifactId>
+            <version>${transcoderVersion}</version>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/AbstractImageLoader.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/AbstractImageLoader.java
new file mode 100644 (file)
index 0000000..0d3681f
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img;
+
+import java.awt.image.BufferedImage;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.hedgecode.chess.img.fs.FileSystemDetector;
+import org.hedgecode.chess.img.fs.FileSystemContractor;
+
+/**
+ * Abstract common image loader with type state of saved resources.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public abstract class AbstractImageLoader implements ImageLoader {
+
+    private static final String IMAGES_DIR =
+            ImageConstants.RESOURCE_ROOT_DIR.concat(ImageConstants.RESOURCE_IMAGES_DIR);
+
+    private static final int DEF_IMAGE_SIZE = 100;
+
+    private Type loadType;
+
+    private URI imageResourceUri;
+
+    public AbstractImageLoader() {
+        loadType = Type.STATELESS;
+        try {
+            if (FileSystemDetector.detectJar(getImageResourceUri())) {
+                loadType = Type.STATEFUL;
+            }
+        } catch (ImageException ignored) {
+        }
+    }
+
+    protected abstract void clear();
+
+    @Override
+    public Type loadType() {
+        return loadType;
+    }
+
+    protected void setLoadType(Type loadType) {
+        if (Type.STATELESS.equals(loadType)) {
+            clear();
+        }
+        this.loadType = loadType;
+    }
+
+    protected URI getImageResourceUri() throws ImageException {
+        if (imageResourceUri == null) {
+            try {
+                imageResourceUri = getClass().getResource(IMAGES_DIR).toURI();
+            } catch (URISyntaxException e) {
+                throw new ImageException("image.unable.access.resource");
+            }
+        }
+        return imageResourceUri;
+    }
+
+    protected Map<String, BufferedImage> loadImages(String imagesPath, ImageFilter filter)
+            throws ImageException
+    {
+        return loadImages(imagesPath, filter, DEF_IMAGE_SIZE);
+    }
+
+    protected Map<String, BufferedImage> loadImages(String imagesPath, ImageFilter filter, int size)
+            throws ImageException
+    {
+        Map<String, BufferedImage> images = new HashMap<>();
+        try (FileSystemContractor fsc = FileSystemDetector.detect(getImageResourceUri())) {
+            try (DirectoryStream<Path> ds =
+                         Files.newDirectoryStream(
+                                 fsc.getPath(imagesPath), filter
+                         )
+            ) {
+                ImageFormatShaper formatShaper = ImageFormatShaper.getInstance();
+                for (Path file : ds) {
+                    String fileName = file.getFileName().toString();
+                    String baseName = FilenameUtils.getBaseName(fileName).toLowerCase();
+                    String imageFormat = FilenameUtils.getExtension(fileName).toLowerCase();
+                    images.put(
+                            baseName,
+                            formatShaper.shape(
+                                    imageFormat,
+                                    fsc.getResourceAsStream(file),
+                                    size
+                            )
+                    );
+                }
+            }
+        } catch (Exception e) {
+            throw new ImageException("image.unable.access.resource", e.getMessage());
+        }
+        return images;
+    }
+
+}
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/Diagram.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/Diagram.java
new file mode 100644 (file)
index 0000000..6d62d86
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img;
+
+import java.awt.image.RenderedImage;
+
+import org.hedgecode.chess.position.Position;
+
+/**
+ * Storage class for chess diagrams.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class Diagram {
+
+    private Position position;
+    private RenderedImage image;
+
+    Diagram(Position position, RenderedImage image) {
+        this.position = position;
+        this.image = image;
+    }
+
+    public Position getPosition() {
+        return position;
+    }
+
+    public RenderedImage getImage() {
+        return image;
+    }
+
+}
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018. Developed by Hedgecode.
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,7 +19,6 @@ package org.hedgecode.chess.img;
 import java.awt.Graphics;
 import java.awt.Image;
 import java.awt.image.BufferedImage;
-import java.awt.image.RenderedImage;
 import java.io.File;
 import java.io.IOException;
 import java.util.Map;
@@ -36,7 +35,7 @@ import org.hedgecode.chess.position.Positions;
 import org.hedgecode.chess.position.Square;
 
 /**
- *
+ * Builder for chess diagrams.
  *
  * @author Dmitry Samoshin aka gotty
  */
@@ -53,12 +52,7 @@ public class DiagramBuilder implements ImageBuilder {
     }
 
     @Override
-    public String build(Position position) {
-        return ""; // todo
-    }
-
-    @Override
-    public RenderedImage build(Position position, String boardType, String pieceType)
+    public Diagram build(Position position, String boardType, String pieceType)
             throws ImageException
     {
         Map<Square, ColorPiece> squares = position.getSquares();
@@ -67,22 +61,22 @@ public class DiagramBuilder implements ImageBuilder {
         PieceSet pieces = pieceSetLoader.load(pieceType);
 
         if (board == null || pieces == null) {
-            throw new ImageException("Couldn't find image resources!"); // todo: locale
+            throw new ImageException("image.unable.find.resource");
         }
 
         int squareSize = board.squareSize();
 
-        BufferedImage diagram = board.render();
-        Graphics diagramGraphics = diagram.getGraphics();
+        BufferedImage image = board.getBoard();
+        Graphics imageGraphics = image.getGraphics();
         for (int y = 0; y < Square.getSize(); ++y) {
             for (int x = 0; x < Square.getSize(); ++x) {
                 Square square = Square.getSquare(x, Square.getSize() - (y + 1));
                 ColorPiece colorPiece = squares.get(square);
                 if (colorPiece != null) {
-                    diagramGraphics.drawImage(
+                    imageGraphics.drawImage(
                             pieces.get(colorPiece).getScaledInstance(
                                     squareSize, squareSize, Image.SCALE_SMOOTH
-                            ),
+                            ), // todo: scale in other place
                             x * squareSize,
                             y * squareSize,
                             null
@@ -90,7 +84,9 @@ public class DiagramBuilder implements ImageBuilder {
                 }
             }
         }
-        return diagram;
+        return new Diagram(
+                position, image
+        );
     }
 
     public static ImageBuilder getInstance() {
@@ -101,7 +97,9 @@ public class DiagramBuilder implements ImageBuilder {
     public static void main(String[] args) throws IOException, ImageException {
 
         ImageIO.write(
-                DiagramBuilder.getInstance().build(Positions.INITIAL.getPosition(), "test", "shade"),
+                DiagramBuilder.getInstance().build(
+                        Positions.INITIAL.getPosition(), "test", "chess24"
+                ).getImage(),
                 ImageFormat.PNG.name(),
                 new File("chessboard" + "." + ImageFormat.PNG.getExt())
         );
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/FilenameUtils.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/FilenameUtils.java
new file mode 100644 (file)
index 0000000..f4f4719
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img;
+
+/**
+ * Utilities for path, file name and extension manipulation.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public final class FilenameUtils {
+
+    private static final String EMPTY_STRING = "";
+
+    private static final char EXTENSION_SEPARATOR = '.';
+
+    private static final char UNIX_SEPARATOR = '/';
+    private static final char WINDOWS_SEPARATOR = '\\';
+
+    private static final String PATH_COLON = ":";
+
+    private static final String JAR_SEPARATOR = ".jar!";
+
+    private static final String OS = System.getProperty("os.name").toLowerCase();
+
+    private static final String WIN_OS_TEMPLATE = "win";
+
+    public static String getName(final String fileName) {
+        if (fileName == null) {
+            return null;
+        }
+        final int endPathIndex = Math.max(
+                fileName.lastIndexOf(UNIX_SEPARATOR),
+                fileName.lastIndexOf(WINDOWS_SEPARATOR)
+        );
+        return fileName.substring(endPathIndex + 1);
+    }
+
+    public static String getBaseName(final String fileName) {
+        return removeExtension(
+                getName(fileName)
+        );
+    }
+
+    public static String getExtension(final String fileName) {
+        if (fileName == null) {
+            return null;
+        }
+        final int extensionPos = fileName.lastIndexOf(EXTENSION_SEPARATOR);
+        return extensionPos < 0
+                ? EMPTY_STRING
+                : fileName.substring(extensionPos + 1);
+    }
+
+    public static String getFullPath(final String parentDir, final String... childDirs) {
+        StringBuilder sb = new StringBuilder();
+        sb.append(parentDir);
+        if (childDirs.length > 0) {
+            for (String childDir : childDirs) {
+                sb.append(isWindows() ? WINDOWS_SEPARATOR : UNIX_SEPARATOR).append(childDir);
+            }
+        }
+        return sb.toString();
+    }
+
+    public static String fixPath(final String path) {
+        if (isWindows()) {
+            return path.startsWith(String.valueOf(UNIX_SEPARATOR))
+                    && path.contains(PATH_COLON)
+                    ? path.substring(1)
+                    : path;
+        }
+        return path;
+    }
+
+    public static String getPathFromJar(final String jarPath) {
+        final int jarEndPos = jarPath.lastIndexOf(JAR_SEPARATOR);
+        return jarEndPos < 0
+                ? EMPTY_STRING
+                : jarPath.substring(jarEndPos + JAR_SEPARATOR.length());
+    }
+
+    private static String removeExtension(final String fileName) {
+        if (fileName == null) {
+            return null;
+        }
+        final int extensionPos = fileName.lastIndexOf(EXTENSION_SEPARATOR);
+        return extensionPos < 0
+                ? fileName
+                : fileName.substring(0, extensionPos);
+    }
+
+    private static boolean isWindows() {
+        return (OS.contains(WIN_OS_TEMPLATE));
+    }
+
+    private FilenameUtils() {
+        throw new AssertionError(
+                "No org.hedgecode.chess.img.FilenameUtils instances!"
+        );
+    }
+
+}
 
 package org.hedgecode.chess.img;
 
+import org.hedgecode.chess.position.Position;
+
 /**
- * Image working Exception.
+ * Common image builder interface.
  *
  * @author Dmitry Samoshin aka gotty
  */
-public class ImageException extends Exception {
-
-    private String message;
-
-    public ImageException(String message) {
-        this.message = message;
-    }
+public interface ImageBuilder {
 
-    public String getMessage() {
-        return message;
-    }
+    Diagram build(Position position, String boardType, String pieceType) throws ImageException;
 
 }
@@ -31,6 +31,9 @@ public final class ImageConstants {
 
     public static final String DARK_SQUARE_FILENAME = "dark";
     public static final String LIGHT_SQUARE_FILENAME = "light";
+    public static final String BOARD_FILENAME = "board";
+
+    public static final String LOCALE_BUNDLE_FILE = "org.hedgecode.chess.img.LocalStrings";
 
     private ImageConstants() {
         throw new AssertionError(
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageException.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageException.java
new file mode 100644 (file)
index 0000000..2a177ae
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img;
+
+import java.util.ResourceBundle;
+
+/**
+ * Image load/build Exception.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class ImageException extends Exception {
+
+    private static final ResourceBundle LOCALE_BUNDLE =
+            ResourceBundle.getBundle(ImageConstants.LOCALE_BUNDLE_FILE);
+
+    private String localeKey;
+    private String message;
+
+    public ImageException(String localeKey) {
+        this.localeKey = localeKey;
+        this.message = null;
+    }
+
+    public ImageException(String localeKey, String message) {
+        this.localeKey = localeKey;
+        this.message = message;
+    }
+
+    public String getLocaleKey() {
+        return localeKey;
+    }
+
+    public String getMessage() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(LOCALE_BUNDLE.getString(localeKey));
+        if (message != null)
+            sb.append(": [").append(message).append("]");
+        return sb.toString();
+    }
+
+}
 
 package org.hedgecode.chess.img;
 
-import java.io.File;
-import java.io.FilenameFilter;
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
 
 /**
- *
+ * Filter for images by name and extention.
  *
  * @author Dmitry Samoshin aka gotty
+ * @see DirectoryStream.Filter
  */
-public class ImageFilter implements FilenameFilter {
+public class ImageFilter implements DirectoryStream.Filter<Path> {
 
     private static final String[] IMAGES_EXTS = ImageFormat.getAllExts();
 
@@ -39,13 +42,17 @@ public class ImageFilter implements FilenameFilter {
     }
 
     @Override
-    public boolean accept(File dir, String name) {
-        return isImageName(name) && isImageExt(name);
+    public boolean accept(Path file) throws IOException {
+        if (Files.isDirectory(file)) {
+            return false;
+        }
+        String filename = file.getFileName().toString();
+        return acceptExt(filename) && acceptName(filename);
     }
 
-    private boolean isImageName(String name) {
+    private boolean acceptName(String filename) {
         if (names != null) {
-            name = name.substring(0, name.lastIndexOf('.'));
+            String name = FilenameUtils.getBaseName(filename);
             for (String imageName : names) {
                 if (imageName.equalsIgnoreCase(name))
                     return true;
@@ -55,8 +62,8 @@ public class ImageFilter implements FilenameFilter {
         return true;
     }
 
-    private boolean isImageExt(String ext) {
-        ext = ext.substring(ext.lastIndexOf('.') + 1);
+    private boolean acceptExt(String filename) {
+        String ext = FilenameUtils.getExtension(filename);
         for (String imageExt : IMAGES_EXTS) {
             if (imageExt.equalsIgnoreCase(ext))
                 return true;
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018. Developed by Hedgecode.
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,41 +23,54 @@ import java.util.List;
 import javax.imageio.ImageIO;
 
 /**
- * Supported image formats for reading/writing.
+ * Supported image formats for reading/writing, indicated by type.
  *
  * @author Dmitry Samoshin aka gotty
  */
 public enum ImageFormat {
 
-    PNG ( new String[]{"png"} ),
-    GIF ( new String[]{"gif"} ),
-    JPG ( new String[]{"jpg", "jpeg"} ),
-    SVG ( new String[]{"svg"} ), // todo
-    BMP ( new String[]{"bmp", "wbmp"} );
+    PNG ( Type.BITMAP, new String[]{"png"}         ),
+    GIF ( Type.BITMAP, new String[]{"gif"}         ),
+    JPG ( Type.BITMAP, new String[]{"jpg", "jpeg"} ),
+    BMP ( Type.BITMAP, new String[]{"bmp", "wbmp"} ),
+    SVG ( Type.VECTOR, new String[]{"svg"}         );
 
-    private String[] fortmatExts;
+    enum Type {
+
+        BITMAP,
+        VECTOR
+
+    }
+
+    private Type formatType;
+    private String[] formatExts;
 
     private boolean isRead;
     private boolean isWrite;
 
     private static String[] allAvailableExts;
 
-    ImageFormat(String[] exts) {
-        fortmatExts = exts;
+    ImageFormat(Type type, String[] exts) {
+        formatType = type;
+        formatExts = exts;
         isRead = isExist(
-                ImageIO.getReaderFormatNames(), fortmatExts
+                ImageIO.getReaderFormatNames(), formatExts
         );
         isWrite = isExist(
-                ImageIO.getWriterFormatNames(), fortmatExts
+                ImageIO.getWriterFormatNames(), formatExts
         );
     }
 
+    public Type getType() {
+        return formatType;
+    }
+
     public String getExt() {
-        return fortmatExts[0];
+        return formatExts[0];
     }
 
     public String[] getExts() {
-        return fortmatExts;
+        return formatExts;
     }
 
     public boolean isRead() {
@@ -99,15 +112,4 @@ public enum ImageFormat {
         return false;
     }
 
-
-/*
-    public static void main(String[] args) {
-        ImageFormat imageFormat = JPG;
-        System.out.println("Supported format: " + imageFormat);
-        imageFormat = findFormat("jpeg");
-        imageFormat = findFormat("svg");
-        imageFormat = findFormat("jpeeg");
-    }
-*/
-
 }
\ No newline at end of file
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageFormatShaper.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageFormatShaper.java
new file mode 100644 (file)
index 0000000..5c1aea2
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img;
+
+import java.awt.image.BufferedImage;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.hedgecode.chess.img.bitmap.BitmapImageShaper;
+import org.hedgecode.chess.img.vector.VectorImageShaper;
+
+import static org.hedgecode.chess.img.ImageFormat.Type;
+
+/**
+ * Shaper for images, indicated by type format.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public final class ImageFormatShaper {
+
+    private static ImageFormatShaper _instance = new ImageFormatShaper();
+
+    private Map<Type, ImageShaper> imageShapers = new HashMap<>();
+
+    private ImageFormatShaper() {
+        imageShapers.put(
+                Type.BITMAP,
+                BitmapImageShaper.create()
+        );
+        imageShapers.put(
+                Type.VECTOR,
+                VectorImageShaper.create()
+        );
+    }
+
+    public BufferedImage shape(String imageFormat, InputStream imageStream, int size)
+            throws ImageException
+    {
+        ImageFormat format = ImageFormat.findFormat(imageFormat);
+        if (format != null) {
+            ImageShaper imageShaper = imageShapers.get(
+                    format.getType()
+            );
+            return imageShaper.shape(imageStream, size);
+        } else {
+            throw new ImageException("image.unknown.image.format", imageFormat);
+        }
+    }
+
+    public static ImageFormatShaper getInstance() {
+        return _instance;
+    }
+
+}
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageShaper.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageShaper.java
new file mode 100644 (file)
index 0000000..36f3e40
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+
+/**
+ * Common image shaper interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface ImageShaper {
+
+    BufferedImage shape(InputStream imageStream, int size) throws ImageException;
+
+    BufferedImage shape(URL imageUrl, int size) throws ImageException;
+
+    BufferedImage shape(File imageFile, int size) throws ImageException;
+
+}
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/bitmap/BitmapImageShaper.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/bitmap/BitmapImageShaper.java
new file mode 100644 (file)
index 0000000..10a8e33
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img.bitmap;
+
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import javax.imageio.ImageIO;
+
+import org.hedgecode.chess.img.ImageException;
+import org.hedgecode.chess.img.ImageShaper;
+
+/**
+ * Shaper for bitmap images.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class BitmapImageShaper implements ImageShaper {
+
+    private BitmapImageShaper() {
+    }
+
+    @Override
+    public BufferedImage shape(InputStream imageStream, int size) throws ImageException {
+        try {
+            return scaledImage(
+                    ImageIO.read(imageStream),
+                    size
+            );
+        } catch (IOException e) {
+            throw new ImageException("image.unable.load.bitmap", e.getMessage());
+        }
+    }
+
+    @Override
+    public BufferedImage shape(URL imageUrl, int size) throws ImageException {
+        try {
+            return scaledImage(
+                    ImageIO.read(imageUrl),
+                    size
+            );
+        } catch (IOException e) {
+            throw new ImageException("image.unable.load.bitmap", e.getMessage());
+        }
+    }
+
+    @Override
+    public BufferedImage shape(File imageFile, int size) throws ImageException {
+        try {
+            return scaledImage(
+                    ImageIO.read(imageFile),
+                    size
+            );
+        } catch (IOException e) {
+            throw new ImageException("image.unable.load.bitmap", e.getMessage());
+        }
+    }
+
+    private BufferedImage scaledImage(BufferedImage image, int size) {
+        if (image.getWidth() == size && image.getHeight() == size) {
+            return image;
+        }
+        BufferedImage scaledImage = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
+        Graphics graphics = scaledImage.createGraphics();
+        graphics.drawImage(
+                image.getScaledInstance(size, size, BufferedImage.SCALE_SMOOTH),
+                0, 0, null
+        );
+        graphics.dispose();
+        return scaledImage;
+    }
+
+    public static ImageShaper create() {
+        return new BitmapImageShaper();
+    }
+
+}
@@ -22,22 +22,29 @@ import java.awt.image.BufferedImage;
 import org.hedgecode.chess.position.Square;
 
 /**
- *
+ * Storage class for chess board images.
  *
  * @author Dmitry Samoshin aka gotty
  */
 public class Board {
 
+    private BufferedImage board;
     private SquarePair<BufferedImage> squares;
+
     private int squareSize;
 
-    Board(SquarePair<BufferedImage> squares) {
+    private Board(SquarePair<BufferedImage> squares) {
         this.squares = squares;
         int width = Math.max(squares.getDark().getWidth(), squares.getLight().getWidth());
         int height = Math.max(squares.getDark().getHeight(), squares.getLight().getHeight());
         this.squareSize = Math.max(width, height);
     }
 
+    private Board(BufferedImage board) {
+        this.board = board;
+        this.squareSize = Math.max(board.getWidth(), board.getHeight()) / Square.getSize();
+    }
+
     public int squareSize() {
         return squareSize;
     }
@@ -46,7 +53,14 @@ public class Board {
         return squareSize * Square.getSize();
     }
 
-    public BufferedImage render() {
+    public BufferedImage getBoard() {
+        if (board == null && squares != null) {
+            board = renderBoard();
+        }
+        return board;
+    }
+
+    private BufferedImage renderBoard() {
         BufferedImage board = new BufferedImage(
                 squareSize * Square.getSize(),
                 squareSize * Square.getSize(),
@@ -68,6 +82,10 @@ public class Board {
         return board;
     }
 
+    public static Board create(BufferedImage board) {
+        return new Board(board);
+    }
+
     public static Board create(SquarePair<BufferedImage> squares) {
         return new Board(squares);
     }
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/board/BoardLoader.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/board/BoardLoader.java
new file mode 100644 (file)
index 0000000..e171418
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img.board;
+
+import java.awt.image.BufferedImage;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.hedgecode.chess.img.AbstractImageLoader;
+import org.hedgecode.chess.img.FilenameUtils;
+import org.hedgecode.chess.img.ImageConstants;
+import org.hedgecode.chess.img.ImageException;
+import org.hedgecode.chess.img.ImageFilter;
+
+/**
+ * Loader for chess board's set of images.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class BoardLoader extends AbstractImageLoader {
+
+    private static final String SQUARES_DIR = ImageConstants.RESOURCE_SQUARES_DIR;
+
+    private static final String SQUARE_DARK = ImageConstants.DARK_SQUARE_FILENAME;
+    private static final String SQUARE_LIGHT = ImageConstants.LIGHT_SQUARE_FILENAME;
+
+    private static final String BOARD = ImageConstants.BOARD_FILENAME;
+
+    private static final String[] BOARD_SQUARE_NAMES = { BOARD, SQUARE_DARK, SQUARE_LIGHT };
+
+    private Map<String, Board> squareSetMap = new HashMap<>();
+
+    @Override
+    public Board load(String name) throws ImageException {
+        Board board;
+        if (Type.STATELESS.equals(loadType()) || !squareSetMap.containsKey(name)) {
+            String boardPath = FilenameUtils.getFullPath(SQUARES_DIR, name);
+            board = loadBoard(boardPath);
+            if (Type.STATEFUL.equals(loadType())) {
+                squareSetMap.put(name, board);
+            }
+        } else {
+            board = squareSetMap.get(name);
+        }
+        return board;
+    }
+
+    @Override
+    public void unload(String name) {
+        if (Type.STATEFUL.equals(loadType()) && squareSetMap.containsKey(name)) {
+            squareSetMap.remove(name);
+        }
+    }
+
+    @Override
+    protected void clear() {
+        squareSetMap.clear();
+    }
+
+    private Board loadBoard(String boardPath) throws ImageException {
+        Map<String, BufferedImage> images =
+                loadImages(
+                        boardPath,
+                        new ImageFilter(BOARD_SQUARE_NAMES)
+                );
+        BufferedImage board = images.get(BOARD);
+        SquarePair<BufferedImage> squarePair = SquarePair.create(
+                images.get(SQUARE_DARK), images.get(SQUARE_LIGHT)
+        );
+        if (board == null && !squarePair.isFilled()) {
+            throw new ImageException("image.incomplete.board.set", boardPath);
+        }
+        return board != null
+                ? Board.create(board)
+                : Board.create(squarePair);
+    }
+
+}
@@ -20,7 +20,7 @@ import java.awt.image.BufferedImage;
 import java.util.Objects;
 
 /**
- *
+ * Storage class for set of images of chess board squares.
  *
  * @author Dmitry Samoshin aka gotty
  */
@@ -29,7 +29,7 @@ public class SquarePair<T> {
     private final T dark;
     private final T light;
 
-    SquarePair(T dark, T light) {
+    private SquarePair(T dark, T light) {
         this.dark = dark;
         this.light = light;
     }
@@ -42,6 +42,13 @@ public class SquarePair<T> {
         return light;
     }
 
+    public boolean isFilled() {
+        if (this.dark == null || this.light == null) {
+            return false;
+        }
+        return true;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (!(o instanceof SquarePair)) {
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/DefFileSystemContractor.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/DefFileSystemContractor.java
new file mode 100644 (file)
index 0000000..ef9fd93
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img.fs;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+
+import org.hedgecode.chess.img.FilenameUtils;
+
+/**
+ * Default FileSystem contractor.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class DefFileSystemContractor implements FileSystemContractor {
+
+    private FileSystem fileSystem;
+    private String rootPath;
+
+    DefFileSystemContractor(URI uri) {
+        fileSystem = FileSystems.getDefault();
+        rootPath = FilenameUtils.fixPath(uri.getPath());
+    }
+
+    @Override
+    public FileSystem getFileSystem() {
+        return fileSystem;
+    }
+
+    @Override
+    public Path getPath(String path) {
+        return fileSystem.getPath(rootPath, path);
+    }
+
+    @Override
+    public InputStream getResourceAsStream(Path file) throws IOException {
+        return new FileInputStream(file.toString());
+    }
+
+    @Override
+    public void close() throws Exception {
+        // do nothing
+    }
+
+}
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/FileSystemContractor.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/FileSystemContractor.java
new file mode 100644 (file)
index 0000000..32f4244
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img.fs;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.FileSystem;
+import java.nio.file.Path;
+
+/**
+ * Common FileSystem contractor interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ * @see FileSystem
+ */
+public interface FileSystemContractor extends AutoCloseable {
+
+    FileSystem getFileSystem();
+
+    Path getPath(String path);
+
+    InputStream getResourceAsStream(Path file) throws IOException;
+
+}
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/FileSystemDetector.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/FileSystemDetector.java
new file mode 100644 (file)
index 0000000..66cd6e5
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img.fs;
+
+import java.io.IOException;
+import java.net.URI;
+
+/**
+ * FileSystem Detector.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public final class FileSystemDetector {
+
+    private static final String JAR_SCHEME_NAME = "jar";
+
+    public static FileSystemContractor detect(URI uri) throws IOException {
+        if (JAR_SCHEME_NAME.equals(uri.getScheme())) {
+            return new JarFileSystemContractor(uri);
+        } else {
+            return new DefFileSystemContractor(uri);
+        }
+    }
+
+    public static boolean detectJar(URI uri) {
+        return JAR_SCHEME_NAME.equals(uri.getScheme());
+    }
+
+}
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/JarFileSystemContractor.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/JarFileSystemContractor.java
new file mode 100644 (file)
index 0000000..a57dfbb
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img.fs;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.util.Collections;
+
+import org.hedgecode.chess.img.FilenameUtils;
+
+/**
+ * FileSystem contractor for jar-files.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JarFileSystemContractor implements FileSystemContractor {
+
+    private FileSystem fileSystem;
+    private String rootPath;
+
+    JarFileSystemContractor(URI uri) throws IOException {
+        fileSystem = FileSystems.newFileSystem(
+                uri, Collections.<String, String>emptyMap()
+        );
+        rootPath = FilenameUtils.getPathFromJar(uri.toString());
+    }
+
+    @Override
+    public FileSystem getFileSystem() {
+        return fileSystem;
+    }
+
+    @Override
+    public Path getPath(String path) {
+        return fileSystem.getPath(rootPath, path);
+    }
+
+    @Override
+    public InputStream getResourceAsStream(Path file) throws IOException {
+        return getClass().getResourceAsStream(file.toString());
+    }
+
+    @Override
+    public void close() throws Exception {
+        fileSystem.close();
+    }
+
+}
@@ -27,7 +27,7 @@ import org.hedgecode.chess.position.ColorPiece;
 import org.hedgecode.chess.position.Piece;
 
 /**
- *
+ * Storage class for set of images of chess pieces.
  *
  * @author Dmitry Samoshin aka gotty
  */
@@ -37,7 +37,7 @@ public class PieceSet {
 
     private static String[] allPieceNames;
 
-    PieceSet() {
+    private PieceSet() {
     }
 
     public void add(String name, BufferedImage image) {
@@ -65,7 +65,7 @@ public class PieceSet {
         return pieceSetMap.get(colorPiece);
     }
 
-    public boolean isFull() {
+    public boolean isFilled() {
         for (ColorPiece colorPiece : ColorPiece.values()) {
             if (!pieceSetMap.containsKey(colorPiece)
                     || (pieceSetMap.get(colorPiece) == null)) {
 
 package org.hedgecode.chess.img.piece;
 
-import java.io.File;
-import java.io.IOException;
+import java.awt.image.BufferedImage;
 import java.util.HashMap;
 import java.util.Map;
 
-import javax.imageio.ImageIO;
-
 import org.hedgecode.chess.img.AbstractImageLoader;
+import org.hedgecode.chess.img.FilenameUtils;
 import org.hedgecode.chess.img.ImageConstants;
 import org.hedgecode.chess.img.ImageException;
 import org.hedgecode.chess.img.ImageFilter;
 
 /**
- *
+ * Loader for chess piece's set of images.
  *
  * @author Dmitry Samoshin aka gotty
  */
 public class PieceSetLoader extends AbstractImageLoader {
 
-    private static final File PIECES_PATH = new File(IMAGES_PATH, ImageConstants.RESOURCE_PIECES_DIR);
+    private static final String PIECES_DIR = ImageConstants.RESOURCE_PIECES_DIR;
 
     private static final String[] PIECES_NAMES = PieceSet.getAllPieceNames();
 
@@ -43,13 +41,11 @@ public class PieceSetLoader extends AbstractImageLoader {
 
     @Override
     public PieceSet load(String name) throws ImageException {
-        PieceSet pieceSet = null;
+        PieceSet pieceSet;
         if (Type.STATELESS.equals(loadType()) || !pieceSetMap.containsKey(name)) {
-            File piecePath = new File(PIECES_PATH, name);
-            if (piecePath.exists() && piecePath.isDirectory()) {
-                pieceSet = loadPieces(piecePath);
-            }
-            if (Type.STATEFUL.equals(loadType()) && pieceSet != null) {
+            String piecePath = FilenameUtils.getFullPath(PIECES_DIR, name);
+            pieceSet = loadPieces(piecePath);
+            if (Type.STATEFUL.equals(loadType())) {
                 pieceSetMap.put(name, pieceSet);
             }
         } else {
@@ -70,25 +66,23 @@ public class PieceSetLoader extends AbstractImageLoader {
         pieceSetMap.clear();
     }
 
-    private PieceSet loadPieces(File piecePath) throws ImageException {
+    private PieceSet loadPieces(String piecePath) throws ImageException {
         PieceSet pieceSet = PieceSet.create();
-        File[] images = piecePath.listFiles(new ImageFilter(PIECES_NAMES));
-        if (images != null) {
-            for (File image : images) {
-                if (image.isFile()) {
-                    String filename = image.getName();
-                    try {
-                        pieceSet.add(
-                                filename.substring(0, filename.lastIndexOf('.')),
-                                ImageIO.read(image)
-                        );
-                    } catch (IOException e) {
-                        throw new ImageException(e.getMessage()); // todo: locale
-                    }
-                }
-            }
+        Map<String, BufferedImage> images =
+                loadImages(
+                        piecePath,
+                        new ImageFilter(PIECES_NAMES)
+                );
+        for (String name : PIECES_NAMES) {
+            pieceSet.add(
+                    name,
+                    images.get(name)
+            );
+        }
+        if (!pieceSet.isFilled()) {
+            throw new ImageException("image.incomplete.piece.set", piecePath);
         }
-        return pieceSet.isFull() ? pieceSet : null;
+        return pieceSet;
     }
 
 }
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/vector/SquareImageTranscoder.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/vector/SquareImageTranscoder.java
new file mode 100644 (file)
index 0000000..deeb890
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img.vector;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.imageio.ImageIO;
+
+import org.apache.batik.transcoder.TranscoderException;
+import org.apache.batik.transcoder.TranscoderInput;
+import org.apache.batik.transcoder.TranscoderOutput;
+import org.apache.batik.transcoder.image.ImageTranscoder;
+
+import org.hedgecode.chess.img.ImageFormat;
+
+/**
+ * Transcoder for vector square images to {@link BufferedImage}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ * @see ImageTranscoder
+ */
+public class SquareImageTranscoder extends ImageTranscoder {
+
+    private final int type;
+    private BufferedImage image;
+
+    SquareImageTranscoder(int type) {
+        this.type = type;
+    }
+
+    SquareImageTranscoder(int type, int size) {
+        this.type = type;
+        addTranscodingHint(ImageTranscoder.KEY_WIDTH, (float) size);
+        addTranscodingHint(ImageTranscoder.KEY_HEIGHT, (float) size);
+
+    }
+
+    @Override
+    protected void setImageSize(float width, float height) {
+        if (width > 0 && height > 0) {
+            super.setImageSize(width, height);
+        }
+    }
+
+    @Override
+    public BufferedImage createImage(int width, int height) {
+        return new BufferedImage(width, height, type);
+    }
+
+    @Override
+    public void writeImage(BufferedImage image, TranscoderOutput to) throws TranscoderException {
+        this.image = image;
+    }
+
+    public BufferedImage transcode(InputStream inputStream) throws TranscoderException {
+        transcode(
+                new TranscoderInput(inputStream),
+                null
+        );
+        return getImage();
+    }
+
+    public BufferedImage getImage() {
+        return image;
+    }
+
+
+    public static void main(String[] args) throws TranscoderException, IOException {
+        SquareImageTranscoder imageTranscoder =
+                new SquareImageTranscoder(BufferedImage.TYPE_INT_ARGB); // , 250
+        ImageIO.write(
+                imageTranscoder.transcode(
+                        ClassLoader.getSystemResourceAsStream("images/pieces/spatial/bb.svg")
+                ),
+                ImageFormat.PNG.name(),
+                new File("bishop" + "." + ImageFormat.PNG.getExt())
+        );
+    }
+
+}
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/vector/VectorImageShaper.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/vector/VectorImageShaper.java
new file mode 100644 (file)
index 0000000..bd11dcf
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img.vector;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import org.apache.batik.transcoder.TranscoderException;
+
+import org.hedgecode.chess.img.ImageException;
+import org.hedgecode.chess.img.ImageShaper;
+
+/**
+ * Shaper for vector images.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class VectorImageShaper implements ImageShaper {
+
+    private VectorImageShaper() {
+    }
+
+    @Override
+    public BufferedImage shape(InputStream imageStream, int size) throws ImageException {
+        SquareImageTranscoder imageTranscoder =
+                new SquareImageTranscoder(BufferedImage.TYPE_INT_ARGB, size);
+        try {
+            return imageTranscoder.transcode(imageStream);
+        } catch (TranscoderException e) {
+            throw new ImageException("image.unable.load.vector", e.getMessage());
+        }
+    }
+
+    @Override
+    public BufferedImage shape(URL imageUrl, int size) throws ImageException {
+        try {
+            return shape(
+                    imageUrl.openStream(),
+                    size
+            );
+        } catch (IOException e) {
+            throw new ImageException("image.unable.load.vector", e.getMessage());
+        }
+    }
+
+    @Override
+    public BufferedImage shape(File imageFile, int size) throws ImageException {
+        try {
+            return shape(
+                    new FileInputStream(imageFile),
+                    size
+            );
+        } catch (FileNotFoundException e) {
+            throw new ImageException("image.unable.load.vector", e.getMessage());
+        }
+    }
+
+    public static ImageShaper create() {
+        return new VectorImageShaper();
+    }
+
+}
diff --git a/chesshog-graphics/src/main/resources/org/hedgecode/chess/img/LocalStrings.properties b/chesshog-graphics/src/main/resources/org/hedgecode/chess/img/LocalStrings.properties
new file mode 100644 (file)
index 0000000..75bd45e
--- /dev/null
@@ -0,0 +1,24 @@
+# Copyright (c) 2018-2019. Developed by Hedgecode.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Default localized string information
+# Localized for Locale en_US
+
+image.unable.access.resource=Unable to access resources of graphic module
+image.unable.find.resource=Unable to find image resources
+image.unable.load.bitmap=Unable to load bitmap image
+image.unable.load.vector=Unable to load vector image
+image.unknown.image.format=Unknown image format
+image.incomplete.board.set=Incomplete board set for load
+image.incomplete.piece.set=Incomplete piece set for load
diff --git a/chesshog-graphics/src/main/resources/org/hedgecode/chess/img/LocalStrings_ru.properties b/chesshog-graphics/src/main/resources/org/hedgecode/chess/img/LocalStrings_ru.properties
new file mode 100644 (file)
index 0000000..8def590
--- /dev/null
@@ -0,0 +1,23 @@
+# Copyright (c) 2018-2019. Developed by Hedgecode.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Localized for Locale ru_RU
+
+image.unable.access.resource=\u041D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u0434\u043E\u0441\u0442\u0443\u043F \u043A \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043C \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043A\u043E\u0433\u043E \u043C\u043E\u0434\u0443\u043B\u044F
+image.unable.find.resource=\u041D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u043D\u0430\u0439\u0442\u0438 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043A\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044B
+image.unable.load.bitmap=\u041D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0440\u0430\u0441\u0442\u0440\u043E\u0432\u043E\u0435 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435
+image.unable.load.vector=\u041D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0432\u0435\u043A\u0442\u043E\u0440\u043D\u043E\u0435 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435
+image.unknown.image.format=\u041D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u044B\u0439 \u0444\u043E\u0440\u043C\u0430\u0442 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F
+image.incomplete.board.set=\u041D\u0435\u043F\u043E\u043B\u043D\u044B\u0439 \u043D\u0430\u0431\u043E\u0440 \u0434\u043B\u044F \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0438 \u0448\u0430\u0445\u043C\u0430\u0442\u043D\u043E\u0439 \u0434\u043E\u0441\u043A\u0438
+image.incomplete.piece.set=\u041D\u0435\u043F\u043E\u043B\u043D\u044B\u0439 \u043D\u0430\u0431\u043E\u0440 \u0434\u043B\u044F \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0438 \u0448\u0430\u0445\u043C\u0430\u0442\u043D\u044B\u0445 \u0444\u0438\u0433\u0443\u0440
index ef93be5..4ad6b23 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-  ~ Copyright (c) 2018. Developed by Hedgecode.
+  ~ Copyright (c) 2018-2019. Developed by Hedgecode.
   ~
   ~ Licensed under the Apache License, Version 2.0 (the "License");
   ~ you may not use this file except in compliance with the License.
         Hedgecode ChessHog Hedgefish Module.
     </description>
 
-    <properties>
-        <chessHogVersion>0.1-SNAPSHOT</chessHogVersion>
-    </properties>
-
     <dependencies>
         <dependency>
             <groupId>org.hedgecode.chess</groupId>
-            <artifactId>chesshog</artifactId>
-            <version>${chessHogVersion}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.hedgecode.chess</groupId>
             <artifactId>chesshog-core</artifactId>
             <version>${chessHogVersion}</version>
         </dependency>
index b32e9d1..3c4b577 100644 (file)
     </description>
 
     <properties>
-        <chessHogVersion>0.1-SNAPSHOT</chessHogVersion>
         <zxingVersion>3.3.3</zxingVersion>
     </properties>
 
     <dependencies>
         <dependency>
             <groupId>org.hedgecode.chess</groupId>
-            <artifactId>chesshog</artifactId>
+            <artifactId>chesshog-core</artifactId>
             <version>${chessHogVersion}</version>
         </dependency>
         <dependency>
             <groupId>org.hedgecode.chess</groupId>
-            <artifactId>chesshog-core</artifactId>
+            <artifactId>chesshog-format</artifactId>
             <version>${chessHogVersion}</version>
         </dependency>
         <dependency>
             <groupId>org.hedgecode.chess</groupId>
-            <artifactId>chesshog-format</artifactId>
+            <artifactId>chesshog-graphics</artifactId>
             <version>${chessHogVersion}</version>
         </dependency>
         <dependency>
diff --git a/chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/ChessQRCodeApp.java b/chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/ChessQRCodeApp.java
new file mode 100644 (file)
index 0000000..fe5d50e
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.qrcode;
+
+import org.hedgecode.chess.ChessHogConsole;
+
+/**
+ * Chess QR Code Main Application.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public final class ChessQRCodeApp {
+
+    private static final String[] QRCODE_MODULE_LOGO = {
+            "                          _                        ",
+            "        ___ ___ ___ ___ _| |___                    ",
+            "       | . |  _|  _| . | . | -_|                   ",
+            "       |_  |_| |___|___|___|___|                   ",
+            "         |_|                    _     _            ",
+            "                    _____ ___ _| |_ _| |___        ",
+            "                   |     | . | . | | | | -_|       ",
+            "                   |_|_|_|___|___|___|_|___|       ",
+            "                                                   "
+    };
+
+    public static void main(String[] args) {
+
+        ChessHogConsole.init();
+
+        for (String line : QRCODE_MODULE_LOGO) {
+            ChessHogConsole.console(line);
+        }
+
+    }
+
+}
\ No newline at end of file
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.hedgecode.chess;
+package org.hedgecode.chess.qrcode;
 
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
@@ -32,7 +32,7 @@ public final class ChessQRCodeConstants {
 
     private ChessQRCodeConstants() {
         throw new AssertionError(
-                "No org.hedgecode.chess.ChessQRCodeConstants instances!"
+                "No org.hedgecode.chess.qrcode.ChessQRCodeConstants instances!"
         );
     }
 
index 5c490de..9844bc2 100644 (file)
@@ -18,8 +18,6 @@ package org.hedgecode.chess.qrcode;
 
 import java.util.ResourceBundle;
 
-import org.hedgecode.chess.ChessQRCodeConstants;
-
 /**
  * Chess-specific QR Codes read/write/parse Exception.
  *
index 1c8f373..e0c1f98 100644 (file)
@@ -17,7 +17,7 @@
 package org.hedgecode.chess.qrcode;
 
 /**
- * Mode of data type stored in Chess-specific QR Codes.
+ * Mode of data type stored in chess-specific QR Codes.
  *
  * @author Dmitry Samoshin aka gotty
  */
@@ -26,18 +26,23 @@ public enum ChessQRCodeMode {
     FEN,
     TCD,
     PGN,
-    TCG;
+    TCG,
+    ZIP;
 
-    static final int CODE_LENGTH = 3;
+    public static final int CODE_LENGTH = 3;
 
-    boolean isPosition() {
+    public boolean isPosition() {
         return FEN.equals(this) || TCD.equals(this);
     }
 
-    boolean isGame() {
+    public boolean isGame() {
         return PGN.equals(this) || TCG.equals(this);
     }
 
+    public boolean isArchive() {
+        return ZIP.equals(this);
+    }
+
     public static ChessQRCodeMode byCode(String code) {
         for (ChessQRCodeMode mode : ChessQRCodeMode.values()) {
             if (mode.name().equals(code))
index a0bbbdf..b10caa4 100644 (file)
@@ -36,8 +36,6 @@ import com.google.zxing.common.HybridBinarizer;
 import com.google.zxing.qrcode.decoder.Decoder;
 import com.google.zxing.qrcode.detector.Detector;
 
-import org.hedgecode.chess.ChessQRCodeConstants;
-
 /**
  * Chess-specific QR Codes reader (image decoder).
  *
@@ -49,7 +47,7 @@ public class ChessQRCodeReader {
 
     private static ChessQRCodeReader _instance = new ChessQRCodeReader();
 
-    private ChessQRCodeReader() {
+    protected ChessQRCodeReader() {
         decoder = new Decoder();
     }
 
@@ -126,20 +124,7 @@ public class ChessQRCodeReader {
             );
         }
 
-        ChessQRCodeMode mode = ChessQRCodeMode.byCode(
-                decoderResult.getText().substring(0, ChessQRCodeMode.CODE_LENGTH)
-        );
-
-        if (mode == null) {
-            throw new ChessQRCodeException(
-                    ChessQRCodeException.Type.READ, "read.unknown.chess.mode"
-            );
-        }
-
-        return new ChessQRResult(
-                mode,
-                decoderResult.getText().substring(ChessQRCodeMode.CODE_LENGTH)
-        );
+        return createResult(decoderResult);
 /*
         ResultPoint[] points = detectorResult.getPoints();
 
@@ -176,6 +161,22 @@ public class ChessQRCodeReader {
 */
     }
 
+    protected ChessQRResult createResult(DecoderResult decoderResult) throws ChessQRCodeException {
+        String result = decoderResult.getText();
+
+        ChessQRCodeMode mode = ChessQRResult.getMode(result);
+        if (mode == null) {
+            throw new ChessQRCodeException(
+                    ChessQRCodeException.Type.READ, "read.unknown.chess.mode"
+            );
+        }
+
+        return new ChessQRResult(
+                mode,
+                ChessQRResult.getContents(result)
+        );
+    }
+
     public static ChessQRCodeReader getInstance() {
         return _instance;
     }
@@ -184,7 +185,7 @@ public class ChessQRCodeReader {
     public static void main(String[] args) {
         try {
             ChessQRResult qrCodeResult = ChessQRCodeReader.getInstance().read(
-                    new File("MyQRCode.png")
+                    new File("qrcode.png")
             );
             System.out.println("Decoded format = " + qrCodeResult.getMode());
             System.out.println("Decoded text = " + qrCodeResult.getContents());
index bc11750..cb2d532 100644 (file)
@@ -35,7 +35,6 @@ import com.google.zxing.qrcode.encoder.ByteMatrix;
 import com.google.zxing.qrcode.encoder.Encoder;
 import com.google.zxing.qrcode.encoder.QRCode;
 
-import org.hedgecode.chess.ChessQRCodeConstants;
 import org.hedgecode.chess.img.ImageFormat;
 
 /**
@@ -47,12 +46,13 @@ public class ChessQRCodeWriter {
 
     private static final int DEF_QUIET_ZONE_SIZE = 4;
     private static final int DEF_QRCODE_BIT_SIZE = 250;
+    private static final int MIN_QRCODE_BIT_SIZE = 50;
 
     private static final ErrorCorrectionLevel DEF_ERR_CORR_LEVEL = ErrorCorrectionLevel.H; // todo: Q
 
     private static ChessQRCodeWriter _instance = new ChessQRCodeWriter();
 
-    private ChessQRCodeWriter() {
+    protected ChessQRCodeWriter() {
     }
 
     public void write(ChessQRCodeMode mode, String contents, ImageFormat format, String qrCodeFilePath)
@@ -139,7 +139,7 @@ public class ChessQRCodeWriter {
         );
     }
 
-    private BitMatrix encode(
+    protected BitMatrix encode(
             ChessQRCodeMode mode,
             String contents,
             int width, int height,
@@ -158,12 +158,14 @@ public class ChessQRCodeWriter {
             );
         }
 
-        if (width < 0 || height < 0) { // todo
+        if (Math.min(width, height) < MIN_QRCODE_BIT_SIZE) { // todo: check for Version
             throw new ChessQRCodeException(
                     ChessQRCodeException.Type.WRITE, "write.qrcode.size.incorrect"
             );
         }
 
+        String qrCodeContents = mode.name().concat(contents);
+
         int quietZone = DEF_QUIET_ZONE_SIZE;
         ErrorCorrectionLevel errorCorrectionLevel = DEF_ERR_CORR_LEVEL;
 
@@ -188,12 +190,10 @@ public class ChessQRCodeWriter {
         }
         hints = newHints;
 
-        String qrCodeText = mode.name().concat(contents);
-
         QRCode qrCode;
         try {
             qrCode = Encoder.encode(
-                    qrCodeText, errorCorrectionLevel, hints
+                    qrCodeContents, errorCorrectionLevel, hints
             );
         } catch (WriterException e) {
             throw new ChessQRCodeException(
@@ -239,7 +239,7 @@ public class ChessQRCodeWriter {
                     ChessQRCodeMode.FEN,
                     "rnbqkbnr/ppp1pppp/8/3p4/4P3/8/PPPP1PPP/RNBQKBNR w KQkq d6 0 2",
                     ImageFormat.PNG,
-                    "./MyQRCode.png"
+                    "./qrcode.png"
             );
 /*
             ChessQRCodeWriter.getInstance().write(
@@ -249,7 +249,7 @@ public class ChessQRCodeWriter {
                             "11.Bf4 b5 12.a4 Bb7 13.Re1 Nd5 14.Bg3 Kc8 15.axb5 cxb5 16.Qd3 Bc6 \n" +
                             "17.Bf5 exf5 18.Rxe7 Bxe7 19.c4 1-0",
                     ImageFormat.PNG,
-                    "./MyQRCode.png"
+                    "./qrcode.png"
             );
 */
         } catch (ChessQRCodeException e) {
index 75df9f9..a0e80c5 100644 (file)
@@ -81,8 +81,8 @@ public final class ChessQRMatrixUtils {
 
 
     static ByteMatrix embedChessLogoPattern(ByteMatrix byteMatrix) {
-        if (byteMatrix == null || byteMatrix.getWidth() < CHESS_LOGO_PATTERN_LENGTH + 14) // todo: 14
-            return null;
+        if (byteMatrix == null || byteMatrix.getWidth() < CHESS_LOGO_PATTERN_LENGTH + 14)
+            return null; // todo: check for Version
 
         int xStart = (byteMatrix.getWidth() - CHESS_LOGO_PATTERN_LENGTH) / 2;
         int yStart = (byteMatrix.getHeight() - CHESS_LOGO_PATTERN_LENGTH) / 2;
index 1b8bbf7..0e2f585 100644 (file)
@@ -23,7 +23,7 @@ import org.hedgecode.chess.position.Parser;
 import org.hedgecode.chess.position.Position;
 
 /**
- * Result storage for Chess-specific QR Codes data.
+ * Result storage for chess-specific QR Codes data.
  *
  * @author Dmitry Samoshin aka gotty
  */
@@ -34,11 +34,12 @@ public class ChessQRResult {
     private Position position;
     private Game game;
 
-    ChessQRResult(ChessQRCodeMode mode, String contents) {
+    public ChessQRResult(ChessQRCodeMode mode, String contents) {
         this.mode = mode;
         this.contents = contents;
     }
 
+/*
     ChessQRResult(Position position) {
         this.position = position;
     }
@@ -46,6 +47,7 @@ public class ChessQRResult {
     ChessQRResult(Game game) {
         this.game = game;
     }
+*/
 
     public ChessQRCodeMode getMode() {
         return mode;
@@ -88,4 +90,14 @@ public class ChessQRResult {
         }
     }
 
+    public static ChessQRCodeMode getMode(String contents) {
+        return ChessQRCodeMode.byCode(
+                contents.substring(0, ChessQRCodeMode.CODE_LENGTH)
+        );
+    }
+
+    public static String getContents(String contents) {
+        return contents.substring(ChessQRCodeMode.CODE_LENGTH);
+    }
+
 }
diff --git a/chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/zip/ZipChessQRCodeReader.java b/chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/zip/ZipChessQRCodeReader.java
new file mode 100644 (file)
index 0000000..8578a8b
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.qrcode.zip;
+
+import java.io.File;
+
+import com.google.zxing.common.DecoderResult;
+
+import org.hedgecode.chess.qrcode.ChessQRCodeException;
+import org.hedgecode.chess.qrcode.ChessQRCodeMode;
+import org.hedgecode.chess.qrcode.ChessQRCodeReader;
+import org.hedgecode.chess.qrcode.ChessQRResult;
+
+/**
+ *
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class ZipChessQRCodeReader extends ChessQRCodeReader {
+
+    private static ZipChessQRCodeReader _instance = new ZipChessQRCodeReader();
+
+    protected ZipChessQRCodeReader() {
+        super();
+    }
+
+    @Override
+    protected ChessQRResult createResult(DecoderResult decoderResult) throws ChessQRCodeException {
+        String result = decoderResult.getText();
+        ChessQRCodeMode mode = ChessQRResult.getMode(result);
+
+        if (ChessQRCodeMode.ZIP.equals(mode)) {
+            String contents = ZipContentInflater.inflate(
+                    ChessQRResult.getContents(result)
+            );
+
+            mode = ChessQRResult.getMode(contents);
+            if (mode == null) {
+                throw new ChessQRCodeException(
+                        ChessQRCodeException.Type.READ, "read.unknown.chess.mode"
+                );
+            }
+
+            return new ChessQRResult(
+                    mode,
+                    ChessQRResult.getContents(contents)
+            );
+        } else {
+            return super.createResult(decoderResult);
+        }
+    }
+
+    public static ZipChessQRCodeReader getInstance() {
+        return _instance;
+    }
+
+
+    public static void main(String[] args) {
+        try {
+            ChessQRResult qrCodeResult = ZipChessQRCodeReader.getInstance().read(
+                    new File("qrcode.png")
+            );
+            System.out.println("Decoded format = " + qrCodeResult.getMode());
+            System.out.println("Decoded text = " + qrCodeResult.getContents());
+        } catch (ChessQRCodeException e) {
+            System.out.println("Could not decode QR Code. Exception: " + e.getMessage());
+        }
+    }
+
+}
diff --git a/chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/zip/ZipChessQRCodeWriter.java b/chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/zip/ZipChessQRCodeWriter.java
new file mode 100644 (file)
index 0000000..6b92e76
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.qrcode.zip;
+
+import java.util.Map;
+
+import com.google.zxing.EncodeHintType;
+import com.google.zxing.common.BitMatrix;
+import org.hedgecode.chess.img.ImageFormat;
+import org.hedgecode.chess.qrcode.ChessQRCodeException;
+import org.hedgecode.chess.qrcode.ChessQRCodeMode;
+import org.hedgecode.chess.qrcode.ChessQRCodeWriter;
+
+/**
+ *
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class ZipChessQRCodeWriter extends ChessQRCodeWriter {
+
+    private static ChessQRCodeWriter _instance = new ZipChessQRCodeWriter();
+
+    protected ZipChessQRCodeWriter() {
+        super();
+    }
+
+    @Override
+    protected BitMatrix encode(
+            ChessQRCodeMode mode,
+            String contents,
+            int width, int height,
+            Map<EncodeHintType,?> hints)
+            throws ChessQRCodeException
+    {
+        if (mode == null || mode.isArchive()) {
+            throw new ChessQRCodeException(
+                    ChessQRCodeException.Type.WRITE, "write.qrcode.mode.null"
+            );
+        }
+
+        if (contents == null || contents.isEmpty()) {
+            throw new ChessQRCodeException(
+                    ChessQRCodeException.Type.WRITE, "write.qrcode.contents.empty"
+            );
+        }
+
+        String zipContents = ZipContentDeflater.deflate(
+                mode.name().concat(contents)
+        );
+
+        return super.encode(
+                ChessQRCodeMode.ZIP, zipContents, width, height, hints
+        );
+    }
+
+    public static ChessQRCodeWriter getInstance() {
+        return _instance;
+    }
+
+
+    public static void main(String[] args) {
+        try {
+            ZipChessQRCodeWriter.getInstance().write(
+                    ChessQRCodeMode.PGN,
+                    "1.e4 c6 2.d4 d5 3.Nc3 dxe4 4.Nxe4 Nd7 5.Ng5 Ngf6 6.Bd3 e6 7.N1f3 h6\n" +
+                            "8.Nxe6 Qe7 9.O-O fxe6 10.Bg6+ Kd8 {Каспаров встряхнул головой} \n" +
+                            "11.Bf4 b5 12.a4 Bb7 13.Re1 Nd5 14.Bg3 Kc8 15.axb5 cxb5 16.Qd3 Bc6 \n" +
+                            "17.Bf5 exf5 18.Rxe7 Bxe7 19.c4 1-0",
+                    ImageFormat.PNG,
+                    "./qrcode.png"
+            );
+        } catch (ChessQRCodeException e) {
+            System.out.println("Could not generate QR Code, Exception: " + e.getMessage());
+        }
+    }
+
+}
diff --git a/chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/zip/ZipContentDeflater.java b/chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/zip/ZipContentDeflater.java
new file mode 100644 (file)
index 0000000..5a2c4fe
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.qrcode.zip;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
+
+import org.hedgecode.chess.qrcode.ChessQRCodeConstants;
+import org.hedgecode.chess.qrcode.ChessQRCodeException;
+
+/**
+ *
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class ZipContentDeflater {
+
+    public static String deflate(String contents) throws ChessQRCodeException {
+        byte[] bytes = contents.getBytes(
+                ChessQRCodeConstants.CHARSET
+        );
+        if (bytes.length > ZipContentUtils.getMaxContentLength()) {
+            throw new ChessQRCodeException(
+                    ChessQRCodeException.Type.PARSE, "zip.max.length.error"
+            );
+        }
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        DeflaterOutputStream zout = new DeflaterOutputStream(
+                bout, new Deflater(Deflater.BEST_COMPRESSION)
+        );
+        try {
+            try {
+                zout.write(bytes);
+            } finally {
+                zout.close();
+                bout.close();
+            }
+        } catch (IOException e) {
+            throw new ChessQRCodeException(
+                    ChessQRCodeException.Type.PARSE, "zip.deflate.write.error", e.getMessage()
+            );
+        }
+        return ZipContentUtils.base64Encode(
+                ZipContentUtils.concat(
+                        bytes.length,
+                        bout.toByteArray()
+                )
+        );
+    }
+
+
+    public static void main(String[] args) throws ChessQRCodeException {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < 10; ++i) {
+            sb.append(i).append("bla-bla-bla").append(i);
+        }
+        String zipContents = ZipContentDeflater.deflate(sb.toString());
+        System.out.println("Zip Contents: " + zipContents);
+        System.out.println("Zip length: " + zipContents.length());
+        String contents = ZipContentInflater.inflate(zipContents);
+        System.out.println("Unzip Contents: " + contents);
+        System.out.println("Unziip length: " + contents.length());
+        System.out.println("Equals: " + sb.toString().equals(contents));
+    }
+
+}
diff --git a/chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/zip/ZipContentInflater.java b/chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/zip/ZipContentInflater.java
new file mode 100644 (file)
index 0000000..0e44138
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.qrcode.zip;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.zip.InflaterInputStream;
+
+import org.hedgecode.chess.qrcode.ChessQRCodeConstants;
+import org.hedgecode.chess.qrcode.ChessQRCodeException;
+
+/**
+ *
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class ZipContentInflater {
+
+    public static String inflate(String zipContents) throws ChessQRCodeException {
+        byte[] zipBytes = ZipContentUtils.base64Decode(zipContents);
+        int length = ZipContentUtils.getZipLength(zipBytes);
+        if (length > ZipContentUtils.getMaxContentLength()) {
+            throw new ChessQRCodeException(
+                    ChessQRCodeException.Type.PARSE, "zip.max.length.error"
+            );
+        }
+        byte[] resultBytes = new byte[length];
+        InflaterInputStream zin = new InflaterInputStream(
+                new ByteArrayInputStream(
+                        ZipContentUtils.getZipBytes(zipBytes)
+                )
+        );
+        try {
+            try {
+                length = zin.read(resultBytes, 0, length); // todo : check length
+            } finally {
+                zin.close();
+            }
+        } catch (IOException e) {
+            throw new ChessQRCodeException(
+                    ChessQRCodeException.Type.PARSE, "zip.inflate.read.error", e.getMessage()
+            );
+        }
+        return new String(
+                resultBytes, 0, length, ChessQRCodeConstants.CHARSET
+        );
+    }
+
+}
diff --git a/chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/zip/ZipContentUtils.java b/chesshog-qrcode/src/main/java/org/hedgecode/chess/qrcode/zip/ZipContentUtils.java
new file mode 100644 (file)
index 0000000..dfd7901
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.qrcode.zip;
+
+import java.util.Arrays;
+import java.util.Base64;
+
+/**
+ *
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class ZipContentUtils {
+
+    private static final int LENGTH_BYTE_COUNT = 4;
+
+    private static final int MAX_CONTENT_LENGTH = 65536;
+
+    public static int getMaxContentLength() {
+        return MAX_CONTENT_LENGTH;
+    }
+
+    public static int getZipLength(byte[] zipBytes) {
+        return fromByteArray(
+                Arrays.copyOf(zipBytes, LENGTH_BYTE_COUNT)
+        );
+    }
+
+    public static byte[] getZipBytes(byte[] zipBytes) {
+        return Arrays.copyOfRange(
+                zipBytes, LENGTH_BYTE_COUNT, zipBytes.length
+        );
+    }
+
+    public static byte[] concat(int length, byte[] bytes) {
+        return concat(
+                toByteArray(length),
+                bytes
+        );
+    }
+
+    public static String base64Encode(byte[] bytes) {
+        return Base64.getEncoder().encodeToString(bytes);
+    }
+
+    public static byte[] base64Decode(String value) {
+        return Base64.getDecoder().decode(value);
+    }
+
+    private static byte[] toByteArray(int value) {
+        return new byte[] {
+                (byte) (value >> 24),
+                (byte) (value >> 16),
+                (byte) (value >> 8),
+                (byte) (value)
+        };
+    }
+
+    private static int fromByteArray(byte[] bytes) {
+        return bytes[0] << 24
+                | (bytes[1] & 0xFF) << 16
+                | (bytes[2] & 0xFF) << 8
+                | (bytes[3] & 0xFF);
+    }
+
+    private static byte[] concat(byte[]... byteArrays) {
+        int length = 0;
+        for (byte[] bytes : byteArrays) {
+            length += bytes.length;
+        }
+        byte[] concatBytes = new byte[length];
+        length = 0;
+        for (byte[] bytes : byteArrays) {
+            if (bytes.length == 0)
+                continue;
+            System.arraycopy(bytes, 0, concatBytes, length, bytes.length);
+            length += bytes.length;
+        }
+        return concatBytes;
+    }
+
+    private ZipContentUtils() {
+        throw new AssertionError(
+                "No org.hedgecode.chess.qrcode.zip.ZipContentUtils instances!"
+        );
+    }
+
+}
index 5c7f3a1..39911c2 100644 (file)
@@ -28,3 +28,6 @@ write.qrcode.contents.empty=Input data is empty
 write.qrcode.size.incorrect=Incorrect QR Code size specified
 write.qrcode.chess.incorrect=Specified size is not suitable for chess QR Code
 write.zxing.qrcode.error=Error encoding of QR code
+zip.max.length.error=Content length exceeds maximum size
+zip.deflate.write.error=Error deflating of content
+zip.inflate.read.error=Error inflating of content
index b396326..5036e83 100644 (file)
@@ -27,3 +27,6 @@ write.qrcode.contents.empty=\u0412\u0445\u043E\u0434\u043D\u044B\u0435 \u0434\u0
 write.qrcode.size.incorrect=\u041D\u0435\u043A\u043E\u0440\u0440\u0435\u043A\u0442\u043D\u043E \u0437\u0430\u0434\u0430\u043D \u0440\u0430\u0437\u043C\u0435\u0440 QR \u043A\u043E\u0434\u0430
 write.qrcode.chess.incorrect=\u0417\u0430\u0434\u0430\u043D\u043D\u044B\u0439 \u0440\u0430\u0437\u043C\u0435\u0440 \u043D\u0435 \u043F\u043E\u0434\u0445\u043E\u0434\u0438\u0442 \u0434\u043B\u044F \u0448\u0430\u0445\u043C\u0430\u0442\u043D\u043E\u0433\u043E QR \u043A\u043E\u0434\u0430
 write.zxing.qrcode.error=\u041E\u0448\u0438\u0431\u043A\u0430 \u043A\u043E\u0434\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F QR \u043A\u043E\u0434\u0430
+zip.max.length.error=\u0414\u043B\u0438\u043D\u0430 \u0441\u043E\u0434\u0435\u0440\u0436\u0438\u043C\u043E\u0433\u043E \u043F\u0440\u0435\u0432\u044B\u0448\u0430\u0435\u0442 \u043C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u043E \u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 \u0440\u0430\u0437\u043C\u0435\u0440
+zip.deflate.write.error=\u041E\u0448\u0438\u0431\u043A\u0430 \u0430\u0440\u0445\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0441\u043E\u0434\u0435\u0440\u0436\u0438\u043C\u043E\u0433\u043E
+zip.inflate.read.error=\u041E\u0448\u0438\u0431\u043A\u0430 \u0440\u0430\u0437\u0430\u0440\u0445\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0441\u043E\u0434\u0435\u0440\u0436\u0438\u043C\u043E\u0433\u043E
  * limitations under the License.
  */
 
-package org.hedgecode.chess;
+package org.hedgecode.chess.qrcode;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
 
 /**
- * Chess QR Code Main Application.
+ * Tests for {@link ChessQRCodeWriter}.
  *
  * @author Dmitry Samoshin aka gotty
  */
-public final class ChessQRCodeApp {
-
-    public static void main(String[] args) {
+@RunWith(JUnit4.class)
+public class ChessQRCodeReaderTest extends Assert {
 
+    @Test
+    public void decode() throws Exception {
 
     }
 
diff --git a/chesshog-qrcode/src/test/java/org/hedgecode/chess/qrcode/ChessQRCodeWriterTest.java b/chesshog-qrcode/src/test/java/org/hedgecode/chess/qrcode/ChessQRCodeWriterTest.java
new file mode 100644 (file)
index 0000000..f4a606f
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.qrcode;
+
+import java.io.File;
+
+import javax.imageio.ImageIO;
+
+import org.hedgecode.chess.img.DiagramBuilder;
+import org.hedgecode.chess.img.ImageFormat;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import org.hedgecode.chess.Builders;
+import org.hedgecode.chess.Parsers;
+import org.hedgecode.chess.position.Position;
+
+/**
+ * Tests for {@link ChessQRCodeWriter}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+@RunWith(JUnit4.class)
+public class ChessQRCodeWriterTest extends Assert {
+
+    private static final String QR_CODE_IMAGE_PATH = "./QRCodeTest.png";
+
+    @Test
+    public void generate() throws Exception {
+        //String expected = "rnbqkbnr/ppp1pppp/8/3p4/4P3/8/PPPP1PPP/RNBQKBNR w KQkq d6 0 2";
+        String expected = "1r2k1r1/pbppnp1p/1b3P2/8/Q7/B1PB1q2/P4PPP/3R2K1 w - - 0 21";
+        //String expected = "4kb1r/p2n1ppp/4q3/4p1B1/4P3/1Q6/PPP2PPP/2KR4 w k - 0 16";
+
+        Position expectedPosition = Parsers.FEN.parser().parse(
+                expected
+        );
+
+        ChessQRCodeWriter.getInstance().write(
+                ChessQRCodeMode.TCD,
+                Builders.TCD.builder().build(expectedPosition),
+                ImageFormat.PNG,
+                QR_CODE_IMAGE_PATH
+        );
+
+        File file = new File(QR_CODE_IMAGE_PATH);
+        String actual = ChessQRCodeReader.getInstance().read(
+                file
+        ).getContents();
+
+        Position actualPosition = Parsers.TCD.parser().parse(
+                actual
+        );
+
+
+/*
+        assertNotNull(actual);
+        assertEquals(expected, actual);
+*/
+
+        System.out.println(actual);
+
+        ImageIO.write(
+                DiagramBuilder.getInstance().build(actualPosition, "test", "shade"),
+                "PNG",
+                new File("chessboard.png")
+        );
+
+
+        System.out.println(
+                Builders.ASCII.builder().build(actualPosition)
+        );
+
+
+    }
+
+}
\ No newline at end of file
index 09bcb27..36b3038 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-  ~ Copyright (c) 2018. Developed by Hedgecode.
+  ~ Copyright (c) 2018-2019. Developed by Hedgecode.
   ~
   ~ Licensed under the Apache License, Version 2.0 (the "License");
   ~ you may not use this file except in compliance with the License.
         Hedgecode ChessHog UCI Module.
     </description>
 
-    <properties>
-        <chessHogVersion>0.1-SNAPSHOT</chessHogVersion>
-    </properties>
-
     <dependencies>
         <dependency>
             <groupId>org.hedgecode.chess</groupId>
-            <artifactId>chesshog</artifactId>
-            <version>${chessHogVersion}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.hedgecode.chess</groupId>
             <artifactId>chesshog-core</artifactId>
             <version>${chessHogVersion}</version>
         </dependency>
diff --git a/pom.xml b/pom.xml
index 4e23027..6db0480 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -1,7 +1,7 @@
 <?xml version='1.0' encoding='UTF-8'?>
 
 <!--
-  ~ Copyright (c) 2018. Developed by Hedgecode.
+  ~ Copyright (c) 2018-2020. Developed by Hedgecode.
   ~
   ~ Licensed under the Apache License, Version 2.0 (the "License");
   ~ you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
         <module>chesshog-core</module>
         <module>chesshog-format</module>
         <module>chesshog-uci</module>
+        <module>chesshog-graphics</module>
         <module>chesshog-hedgefish</module>
         <module>chesshog-dbetude</module>
         <module>chesshog-qrcode</module>
@@ -33,7 +34,7 @@
     <parent>
         <groupId>org.hedgecode.maven</groupId>
         <artifactId>lib-parent</artifactId>
-        <version>2</version>
+        <version>3</version>
         <relativePath>../lib-parent/pom.xml</relativePath>
     </parent>
 
 
     <name>Hedgecode ChessHog</name>
     <description>
-        Hedgecode ChessHog.
+        Hedgecode ChessHog is a chess project that includes modules with different functionality, such as:
+
+        * own internal format for the presentation of chess games and positions, which makes
+          it possible to use this project as API library for various chess Java applications;
+        * ability to work with various formats of chess games and diagrams (e.g. PGN, FEN),
+          including the functionality of generating chess positions in ASCII format,
+          as well as Wikipedia format;
+        * provide full functionality for working with UCI (Universal Chess Interface) protocol,
+          which allows both connecting external UCI engines and developing your own
+          using API of UCI module with a set of necessary interfaces described in it;
+        * building chess diagrams in the form of images with a diverse set of chess pieces;
+        * ability to record chess games and positions in the form of a QR code,
+          as well as recognition of this chess QR code.
     </description>
     <inceptionYear>2018</inceptionYear>
 
@@ -70,6 +83,7 @@
     </distributionManagement>
 
     <properties>
+        <chessHogVersion>0.1-SNAPSHOT</chessHogVersion>
         <junitVersion>4.12</junitVersion>
         <commonsConfigVersion>1.10</commonsConfigVersion>
         <commonsCollectionVersion>3.2.1</commonsCollectionVersion>