[JAVA] Ich habe Mugenkura Sushi Gacha gemacht

GoToEat-Kampagne im Oktober gestartet Verwenden Sie sie? GoToEat-Kampagne des Ministeriums für Land- und Forstwirtschaft und Fischerei

Ich habe es oft benutzt, aber es scheint, dass "Mugenkura Sushi" auf den Straßen beliebt ist. Sie können an den Punkten essen, die Sie mit GoToEat erhalten, und Sie können mit dieser Mahlzeit wieder Punkte erhalten, sodass Sie Kura-Sushi viele Male zu einem guten Preis essen können. (Abgesehen von der moralischen Geschichte) Kurasushi Official GoToEat Campaign Page

Um bei GoToEat Punkte zu erhalten, müssen Sie mindestens 500 Yen einschließlich Steuern für das Mittagessen und 1000 Yen einschließlich Steuern für das Abendessen bei Kura Sushi essen. Deshalb habe ich "Infinite Kura Sushi Gacha" gemacht, das zufällig im Kura Sushi-Menü angezeigt wird, wenn es den geltenden Preis überschreitet.

Klicken Sie hier für die Webanwendung, die ich erstellt habe ↓ ** Mugenkura Sushi Gacha **

Diesmal habe ich das "Spring Boot" Framework verwendet. Der gesamte Code ist auf github ↓ verfügbar https://github.com/yutwoking/eternalKurazushi

Ich werde diesen Artikel als einen Schritt bei der Erstellung dieser Apps in der Zukunft belassen.

Annahmen wie Anwendungserstellungsumgebung und Verwendungsrahmen

Rauer Fluss

  1. Implementierung des logischen Teils
  1. Spring Boot Framework Teil --build.gradle Beschreibung --Einen Launcher erstellen --Erstellen eines Controllers --html Erstellung (Ansicht erstellen)

  2. Veröffentlichung von Webanwendungen (AWS)

1. Implementierung des logischen Teils

Lesemenü von der offiziellen Website von Kura Sushi

Laden Sie zunächst das Menü von der offiziellen Website. Es ist notwendig, das HTML von Official Menu Site zu analysieren. Analysieren Sie mit einer Bibliothek namens Jsoup.

Verwendung von Jsoup Reference https://www.codeflow.site/ja/article/java-with-jsoup

Die Implementierung des Analyseteils ist wie folgt

LoadMenu.java


private static List<MenuModel>  loadMenuFromSite(String url) throws IOException{
    	List<MenuModel> models = new LinkedList<>();

    	Document doc = Jsoup.connect(url).get();
    	Elements menusBySection = doc.select(".section-body");
    	for (Element section : menusBySection) {
    		String sectionName  = section.select(".menu-section-header h3").text();
    		if (!StringUtils.isEmpty(sectionName)) {
    			Elements menus  = section.select(".menu-list").get(0).select(".menu-item");
    			for (Element menu : menus) {
    				String name = menu.select(".menu-name").text();
    				Elements summary = menu.select(".menu-summary li");

    				if (summary.size() >2) {
    					int price  = stringToInt(summary.get(0).select("p").get(0).text());
    					int kcal  = stringToInt(summary.get(0).select("p").get(1).text());
    					String area = summary.get(1).select("p").get(1).text();
    					boolean takeout = toBoolean(summary.get(2).select("p").get(1).text());
    					models.add(new MenuModel(name, price, kcal, area, takeout, sectionName));
    				} else if (summary.size() == 2) {
    					int price  = stringToInt(summary.get(0).select("p").get(0).text());
    					int kcal  = stringToInt(summary.get(0).select("p").get(1).text());
    					String area = "";
    					boolean takeout = toBoolean(summary.get(1).select("p").get(1).text());
    					models.add(new MenuModel(name, price, kcal, area, takeout, sectionName));
    				}
    			}
    		}
    	}
    	return models;
    }

Als grundlegende Verwendung von JSoup,


Document doc = Jsoup.connect(url).get();

Lesen Sie die URL HTML mit

Elements elements = doc.select(".section-body");

Verwenden Sie diese Auswahlmethode, um das relevante Element zu extrahieren.

Ich bedauere, dass der Implementierungscode schwer zu erkennen ist, da die if- und for-Anweisungen verschachtelt sind. .. ..

Speicher- / Extraktionsteil in der Datenbank

Als nächstes folgt die Implementierung rund um die Datenbank. Ich verwende ein Java DB-Zugriffsframework namens Doma2. Klicken Sie hier für den Doma2-Beamten

Doma hat die folgenden Funktionen.

· Verwenden Sie die Anmerkungsverarbeitung, um Code zur Kompilierungszeit zu generieren und zu validieren · Kann Spaltenwerte in der Datenbank verhaltensbezogenen Java-Objekten zuordnen ・ Eine SQL-Vorlage namens 2-Wege-SQL kann verwendet werden. -Java 8 java.time.LocalDate, java.util.Optional und java.util.stream.Stream können verwendet werden. -Keine Abhängigkeit von anderen Bibliotheken als JRE

Es ist ein Framework, das ich oft benutze, weil mir persönlich die Tatsache gefällt, dass es mit SQL-Dateien verwaltet werden kann. Die Verwendung ist offiziell und japanisch, daher ist es gut, darauf zu verweisen. Der Implementierungscode wird hier weggelassen. Der gesamte Code ist auf github ↓ verfügbar https://github.com/yutwoking/eternalKurazushi

Gacha-Logikteil

Gacha.java



public static List<MenuModelForSearch> getResult(Areas area, boolean isLunch){
		List<MenuModelForSearch> result  = new ArrayList<>();
//Lagern Sie 500 zum Mittagessen und 1000 zum Abendessen in der Schwelle
		int threshold = getThreshold(isLunch);
//Speichern Sie alle Menüs in Kandidaten
		List<MenuModelForSearch> candidates = MenuCaches.getSingleton().getMenuList(area, isLunch);

//Überprüfen Sie, ob der Gesamtbetrag des erfassten Menüs den Schwellenwert überschreitet, und fügen Sie nach dem Zufallsprinzip Menüs von Kandidaten hinzu, bis der Schwellenwert überschritten wird.
		while (isOverThreshold(threshold, result) == false) {
			addElement(result, candidates);
		}
//Überprüfen Sie abschließend, ob das Mittagsmenü enthalten ist. Wenn das Mittagsmenü enthalten ist, ist das Ergebnis nur das Mittagsmenü.
		checkIncludeLunchMenu(result);

		return result;
	}

Siehe Ganzer Code für jede Methode.

2. Spring Boot Framework Teil

In Bezug auf SpringBoot habe ich auf die folgende Site verwiesen. https://qiita.com/gosutesu/items/961b71a95daf3a2bce96 https://qiita.com/opengl-8080/items/eb3bf3b5301bae398cc2 https://note.com/ymzk_jp/n/n272dc9e5c5d3

Beschreibung von build.gradle

Fügen Sie build.gradle Plugins und Bibliotheken hinzu, damit gradle das Spring Boot-Framework verwenden kann.

Der Teil, in dem das eigentliche build.gradle dieser Zeit als // Spring-Boot-Zusatzteil kommentiert wird, wird in ↓ hinzugefügt.

build.gradle


plugins {
    // Apply the java plugin to add support for Java
    id 'java'

    // Apply the application plugin to add support for building a CLI application
    id 'application'
    id 'eclipse'
    id 'com.diffplug.eclipse.apt' version '3.25.0'

    id 'org.springframework.boot' version '2.3.5.RELEASE' //spring-Boot-Postscript-Teil
    id 'io.spring.dependency-management' version '1.0.10.RELEASE'//spring-Boot-Postscript-Teil
}

version = '2.26.0-SNAPSHOT'
ext.dependentVersion = '2.24.0'

task copyDomaResources(type: Sync)  {
    from sourceSets.main.resources.srcDirs
    into compileJava.destinationDir
    include 'doma.compile.config'
    include 'META-INF/**/*.sql'
    include 'META-INF/**/*.script'
}

compileJava {
    dependsOn copyDomaResources
    options.encoding = 'UTF-8'
}

compileTestJava {
    options.encoding = 'UTF-8'
    options.compilerArgs = ['-proc:none']
}

repositories {
    mavenCentral()
    mavenLocal()
    maven {url 'https://oss.sonatype.org/content/repositories/snapshots/'}
}

dependencies {
    // Use JUnit test framework
    testImplementation 'junit:junit:4.12'

    // https://mvnrepository.com/artifact/org.jsoup/jsoup
    compile group: 'org.jsoup', name: 'jsoup', version: '1.13.1'

    // https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
    compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.11'

    annotationProcessor "org.seasar.doma:doma:${dependentVersion}"
    implementation "org.seasar.doma:doma:${dependentVersion}"
    runtimeOnly 'com.h2database:h2:1.3.175'
    // https://mvnrepository.com/artifact/org.postgresql/postgresql
    compile group: 'org.postgresql', name: 'postgresql', version: '42.2.8'

	// https://mvnrepository.com/artifact/com.zaxxer/HikariCP
    compile  group: 'com.zaxxer', name: 'HikariCP', version: '3.4.1'

	// https://mvnrepository.com/artifact/javax.inject/javax.inject
    compile group: 'javax.inject', name: 'javax.inject', version: '1'

    // https://mvnrepository.com/artifact/io.vavr/vavr
	compile group: 'io.vavr', name: 'vavr', version: '0.10.2'

	// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-thymeleaf
	compile group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf', version: '2.3.5.RELEASE'//spring-Boot-Postscript-Teil

    // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web
	compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.3.5.RELEASE'//spring-Boot-Postscript-Teil

	// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter
	compile group: 'org.springframework.boot', name: 'spring-boot-starter', version: '2.3.5.RELEASE'//spring-Boot-Postscript-Teil

}


//spring-BootJar-Task hinzugefügt, um das Boot-Projekt in Betrieb zu nehmen
bootJar { 
    launchScript()
}

application {
    // Define the main class for the application
    mainClassName = 'eternalKurazushi.ServerLuncher'
}

eclipse {
    classpath {
        file {
            whenMerged { classpath ->
                classpath.entries.removeAll { it.path == '.apt_generated' }
            }
            withXml { provider ->
                def node = provider.asNode()
                // specify output path for .apt_generated
                node.appendNode( 'classpathentry', [ kind: 'src', output: 'bin/main', path: '.apt_generated'])
            }
        }
    }
    jdt {
        javaRuntimeName = 'JavaSE-11'
    }
}

Launcher erstellen

ServerLuncher.java



@SpringBootApplication
public class ServerLuncher {

	public static void main(String[] args) throws Exception {
        SpringApplication.run(ServerLuncher.class, args);
        LoadMenu.init();
        MenuCaches.getSingleton().load();
    }

}

Sie müssen lediglich die Annotation @SpringBootApplication hinzufügen und SpringApplication.run implementieren.

LoadMenu.init();
MenuCaches.getSingleton().load();

Dieser Teil liest das Menü beim Start des Servers und speichert es in der DB, so dass das Menü auch einen Speicher hat. Mit dieser Konfiguration benötige ich möglicherweise keine Datenbank, aber ich verwende die Datenbank auch für den Fall, dass sie in Zukunft erweitert wird (wahrscheinlich nicht erweitert).

Controller erstellen

FrontController.java



@Controller
public class FrontController {
	@RequestMapping("/")
	public String index() {
		return "index";
	}

	@RequestMapping(value = "/result", method = RequestMethod.POST)
	public String getResult(@RequestParam("radio_1") String eatTime, @RequestParam("radio_2") String areaString, Model model) {
		if (StringUtils.isEmpty(eatTime) || StringUtils.isEmpty(eatTime)) {
			return "error";
		}

		boolean isLunch = eatTime.equals("Mittagessen") ? true : false;
		Areas area = Areas.Ostjapan;
		if (areaString.equals("Westjapan")) {
			area = Areas.Westjapan;
		} else if (areaString.equals("Kyushu-Okinawa")) {
			area = Areas.Kyushu;
		}

		List<MenuModelForSearch> gachaResult = Gacha.getResult(area, isLunch);
		model.addAttribute("list", gachaResult);
		model.addAttribute("sum", getSumString(gachaResult));
		model.addAttribute("time", eatTime);
		model.addAttribute("area", areaString);
		return "result";
	}

Implementieren Sie den Controller mithilfe der Annotation @Controller. Geben Sie den entsprechenden Pfad mit der Annotation @RequestMapping an. Dies ist ähnlich wie bei jax-rs. Empfangen Sie Werte aus HTML mithilfe der Annotation @RequestParam.

model.addAttribute("list", gachaResult);

Sie können mit addAttribute einen Wert an HTML übergeben. In diesem Beispiel wird der Wert von gachaResult mit der Liste der Variablennamen an HTML übergeben.

return "result";

Gibt die HTML-Vorlage von / resources / templates / [Rückgabewert von Controller] .html zurück. In diesem Beispiel wird /resources/templates/result.html gelesen und zurückgegeben.

HTML-Erstellung (Ansichtserstellung)

result.html


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Mugenkura Sushi Gacha</title>
</head>
<body bgcolor=#99FFFF>
	<div style="text-align: center">
		<main>
			<h1>Mugenkura Sushi Gacha</h1>
			<p th:text="${time} + '  /  ' + ${area}" class="description"></p>
			<table border="1" align="center">
				<tr>
					<th>Art</th>
					<th>Produktname</th>
					<th>Preis (ohne Steuern)</th>
					<th>Kalorie</th>
					<!--
					<th>Service Bereich</th>
					<th>Wegbringen</th>
					-->
				</tr>
				<tr th:each="menu : ${list}">
					<td th:text="${menu.type}"></td>
					<td th:text="${menu.name}"></td>
					<td th:text="${menu.price} + 'Kreis'"></td>
					<td th:text="${menu.kcal} + 'kcal'"></td>
					<!--
					<td th:text="${menu.area}"></td>
					<td th:text="${menu.takeout} ? 'Ja' : '不Ja'"></td>
					-->
				</tr>
			</table>
			<h3>
				<p th:text="${sum}" class="sum"></p>
			</h3>
			<br>

			<form method="POST" action="/result">
				<input type="hidden" name="radio_1" th:value="${time}"> <input
					type="hidden" name="radio_2" th:value="${area}">
				<div style="margin: 2rem 0rem">
					<input type="submit" value="Drehen Sie die Gacha unter den gleichen Bedingungen erneut"
						style="width: 250px; height: 50px">
				</div>
			</form>
			<form method="GET" action="/">
				<div style="margin: 2rem 0rem">
					<input type="submit" value="Rückkehr">
				</div>
			</form>
		</main>
	</div>
</body>
</html>

th: value = "$ {Variablenname}" Dann kann der von der Steuerung empfangene Wert verwendet werden. Sie können einen Wert an die Steuerung übergeben, indem Sie eine Eingabe erstellen und mithilfe des Formular-Tags einen Namen angeben.

3. Veröffentlichung von Webanwendungen (AWS)

Dieses Mal habe ich AWS verwendet, um eine Webanwendung zu veröffentlichen. Es ist eine einfache App, also habe ich sie benutzt

es ist dunkel. Empfohlen für Anfänger, da dieses Buch sehr höflich ist und geübt werden kann. [Netzwerk- und Serverkonstruktion aus Amazon Web Services Basics Revised Edition](https://www.amazon.co.jp/Amazon-Web-Services-%E5%9F%BA%E7%A4%8E%E3%81% 8B% E3% 82% 89% E3% 81% AE% E3% 83% 8D% E3% 83% 83% E3% 83% 88% E3% 83% AF% E3% 83% BC% E3% 82% AF- % E3% 82% B5% E3% 83% BC% E3% 83% 90% E3% 83% BC% E6% A7% 8B% E7% AF% 89 / dp / 4822237443)

Schließlich

Es ist schon eine Weile her, dass ich etwas außerhalb der Arbeit geschaffen habe. Arbeitsprogrammierung macht Spaß, aber auch privates Programmieren macht Spaß (Auswahl eines Frameworks, Schaffung einer Umgebung usw.). Daher möchte ich meine Fähigkeiten regelmäßig verbessern.

Wenn ich Zeit habe, möchte ich an Folgendem arbeiten.

Recommended Posts

Ich habe Mugenkura Sushi Gacha gemacht
Ich habe StringUtils.isBlank gemacht
Ich habe ein Roulette in Java gemacht.
Ich habe eine Chat-App erstellt.