エンターテイメント!!

遊戯王好きのJavaエンジニアのブログ。バーニングソウルを会得する特訓中。

【Java】ジャロ・ウィンクラー距離を試してみる

経緯

RSSリーダーを作っているのだが、登録しているサイトが膨大になり、タイトルからある程度、類似した項目を抽出できないかと調査した。
その結果、ジャロ・ウィンクラー距離にたどり着いたので、とりあえず試してみる。

定義

ジャロ・ウィンクラー距離に最初からたどり着いたわけではなく、レーベンシュタイン距離の方が先にたどり着いた。
ちょっと、判定方法が安易だなと思って、もう少し深く調べたら、ジャロ・ウィンクラー距離にたどり着いたので試してみる

wikipedia

ジャロ・ウィンクラー距離 - Wikipedia

全然意味がわからねぇ。。。
調べた感じ、文字列を置換・編集して同じ文字列になる距離を測ることで、一致度を判定しているらしい。

実装

今回の環境

Java11
IntelliJ IDEA 2022.1.1 (Community Edition)
Gradle 5.5

build.gradle

    // https://mvnrepository.com/artifact/org.apache.lucene/lucene-spellchecker
    implementation group: 'org.apache.lucene', name: 'lucene-spellchecker', version: '3.6.2'

    // https://mvnrepository.com/artifact/org.apache.lucene/lucene-analyzers-kuromoji
    implementation group: 'org.apache.lucene', name: 'lucene-analyzers-kuromoji', version: '8.11.1'

↑のやつをdependenciesに加えればイケるはず。

サンプル実装

import org.apache.lucene.search.spell.JaroWinklerDistance;

public class Test {

  public static void main(String[] args) {
    String str1 = "足なんて飾りです。偉い人にはそれが分からんのです。";
    String str2 = "胸なんて飾りです。男にはそれが分からんのです。";

    JaroWinklerDistance jaro = new JaroWinklerDistance();

    System.out.println(jaro.getDistance(str1, str2));
  }
}

※実装内容に他意はありません。

予防線張っておかないと、今の御時世、怖いからね!

使い方は簡単で、JaroWinklerDistanceってのを生成して、getDistanceメソッドで比較したい文字列を渡すだけ。
それだけで結果が見える。
ジャロ・ウィンクラー距離のアルゴリズムは、最初の頃は知りたいと思ったけど、ソース見てその気は失せた。

実行結果

0.91768116

かなり似てる判定になってますね。

逆に、ガンダム語録を変えて比較してみると

    String str1 = "足なんて飾りです。偉い人にはそれが分からんのです。";
    String str2 = "親父にもぶたれたことないのに!";
0.3777778

ふむ。。。
ちゃんと文章を見ているけど、さすがに、意味や背景は考慮してないな。

所感

できれば、意味を考えて距離計算できるといいんだけどなぁ。。。
たしか、ウィキペディアで該当ページまでたどり着けるまで、どれくらいか判定するサービスが会ったような気がする。
それと組み合わせてみると面白そうだと思った。※やる気はない

あと、いろいろ調べてて思ったけど、ベクトル計算が重要だなと思った。
どのアルゴリズムを見ても、ベクトル計算が必須。
いかに数値に置き換えるかが重要だった。
学生諸君は、ちゃんと数学は勉強したほうがいい。
分からなくても、概要は把握した方がいい。

参考サイト

2つの文字列がどれだけ類似しているかを判定するレーベンシュタイン距離とジャロ・ウィンクラー距離(Java編) | ぱーくん plus idea

【技術解説】似ている文字列がわかる!レーベンシュタイン距離とジャロ・ウィンクラー距離の計算方法とは - ミエルカAI は、自然言語処理技術を中心とした、RPA開発・サイト改善・流入改善レコメンドエンジンを開発

2022/05/30週 気づきと振り返り 開発環境なんとかなりませんかねぇ。。。

業務こなしての問題・気づき

ログ調査

結合フェーズに入って、ログを見て、挙動調査しているのだが、マジでハゲそう。。。。

原因が特定できず、ログとにらめっこして、時間だけが溶けていくので、ものすごい焦るんだよね。。。
ある程度、調査しても進展がなかったら、やり方を変える方がいいと学びましたとさ。

開発環境

ビルドが。。。

ビルドが遅すぎる。。。
いらないソース削ったりしてなんとかしてるけど、資材の不整合がおきて実行時にエラーが出たりすると、かなり混乱する。

本来ならば、それを考慮してシステム配置を考えるべきだったが、それを失敗すると、開発効率に甚大な影響があると学びましたとさ。。。。
それが、今後に活きてくるのかは、分からんけど。

Mockito

UnnecessaryStubbingExceptionの発生

使ってないmockがあると、発生するらしい。
最初、それが分からなくて、設定なにか間違ったか凄くコードを疑ってたけど、俺は何も悪くなかったんだ!悪いのは俺の周りの環境!

Java: Mockitoでハマった落とし穴5つとその解決方法 - Qiita

UnnecessaryStubbingException - mockito-core 2.6.5 javadoc

mockito blog: New Mockito API: lenient()

2022/05/23週 気づきと振り返り 頭ハゲそう

業務こなしての問題・気づき

Java

Spring

Validator愚痴1

@validatedで入力チェックしているのだが、BindingResultをメソッド引数に追加してないため、validationエラーが発生したときにメソッドが呼ばれずに、なんで?って2日くらい悩んでた。
俺が実装した画面だったら気づいたかも知れないが、下手に自動生成しているから、可能性の考慮から外れるんだよね。。。
それについての愚痴は、後記の通り

Validator愚痴2

入力チェックをvalidatorでやるのはいいんだけど、いろんなところに設定が飛ぶせいで、無茶苦茶メンテしにくい。 利用しないほうがメンテしやすいのではないかと感じたが、俺だけだろうか?
かなり頭を抱えながら設定を確認していた。
デバックしにくいのも難点だと思う。

validatorの要素数チェック

Spring使って開発しているんだが、リスト形式のデータの場合、デフォルトで要素数チェックが入ってしまうらしい。。。
デフォルトだと256件。
単体のときは発生せず、結合になって本番相当のデータを操作して初めて気づいた。
原因を特定するまで、無茶苦茶時間がかかった。。。
まぁ、これにたどり着くまでに、crsfトークンの問題があったりして、いろんなところに確認依頼出したり、打ち合わせ出たり、シンドかった。。。
メンタルやられてるのに、そういうのに出るのは、かなり辛いんだよね。。。
誰か、もっと俺を甘やかして!!

DataBinder (Spring Framework API) - Javadoc

自動生成

障害対応・バグ修正が難しい

自動生成される内容を完全に把握してないと、バグ修正が難しい。
実際、自動生成されたものが意図したものではないけど、正常ケースが通る場合、何が悪いのか、かなり難儀な調査をした。

バグが発生しないと思い込むせいで、可能性から除外してしまい、改修が面倒になる。

やるならソースを全くイジらない自動生成か、実装は人がやるのどちらかにしないと、見えない工数がかかってくる。
しかも、不具合

雑記

今週もキツかった。。。
もう、ドツボにはまることが多くて、マジでハゲそう。。。

温泉旅行でもしてゆっくり過ごす日をどこかで作りたい。
GWは、人と会いたくなくて、ずっと家で籠もってたから、6月あたりで出かけようかなと画策中。
いつもだと、箱根あたりに行くんだけど、気分変えて、別の場所がいいかな?
候補としては、熱海、鬼怒川、草津あたりを考えてる。

Webスクレイピング周りの調査結果まとめ

きっかけ

webページ解析してみたくて、いろいろ調べた

調査内容まとめ

基本的に、jsoupってライブラリを使えば、webページの情報をオブジェクト化してくれる。
あとは、cssの知識と正規表現の知識があれば、データを引っ張ってこれることまでは確認できた。

問題は、動的webページの解析。

いろいろ調べたが、HtmlUnit使えばいいらしいってことまで調査できたが、自分が使ったサイトでは、無理だった。
他にも、seleniumのライブラリ使って動的サイトで最終的なwebページの情報を取ろうと思ったけど、無理だった。
ajax許可しているはずなんだけど、できてないのは、何かしらの原因があると思っているけど、それが何なのか調査しているうちに、心が折れてしまったよ。。。

javaのライブラリでは無理だったのだが、pythonとかjsのライブラリならイケるのだろうか?

あと、json形式でデータを持っているパターンがあって、それは、正規表現で抽出して、jacksonに食わせてやったんだけど、階層構造が複雑すぎて萎えた。。。
json構造を分析してjavaファイルを作成してくれるサービスが欲しいんだけど、全部1ファイルで出力するやつで、「そうじゃないんだよ!!!」って心の中で叫んでた。
結局、人力でオブジェクト作成したけど、今後もなにかありそうだから、生成するやつを作っておきたい。

まとめ

javaだと、webスクレイピングは、静的解析なら十分にやれることが分かった。
ただ、cssの知識が必須。
あとは、文字列操作とかのために、正規表現とかもいる。

動的webページの解析は、サイトによってできたりできなかったりがある気がする。
ヘッドレスブラウザが充実すれば、javaもワンチャンとは思うが、現状、進化の早いブラウザの実装に付いて行ける力のあるライブラリは、ない気がしている。

その他雑記

いろいろ調べてて思ったけど、ブラウザのサポートが、chromefirefoxのエンジン大半だった。
firefox民なのだが、調べてるとchromeの情報が大量に出てくるので、憤りを覚える。
「そのうち、独占禁止法とかに触れてしまうのでは?」って思うのだが、ブラウザ戦争は、このままchrome独り勝ち状態になってしまうん??
潮目が変わったと思うのは、firefoxのアドオン切りのあたりからだろうと思っている。
firebugsとか、お気に入りのアドオンが使えなくなって、chromeに乗り換えた人が多かったんだと思う。俺も一時期乗り換えてたけど、chromeのUIがどうしても気に入らなくてfirefoxに戻った。
chromeのUIが、ものすごく嫌いだから、firefox使い続けているんだけど、このまま行くと、chrome以外の選択肢がなくなりそうで怖い。
レンダリングエンジンも、chromeの独り勝ち状態にさせるのは、まずいと思うんだけど、どうすりゃいいんだろう?

cssの知識は、stylusで付けた。
cssの知識が薄いwebエンジニアって、結構いると思うんだけど、どうだろう?
使ってないと、すぐ陳腐化する気がする。
俺も完璧って訳じゃないけど、アクセスしたり調査するくらいの知識は付けた。
擬似クラス周りは、さっぱり分からない。

Swiperを使ってみた

きっかけ

ルーセルスライダーでリストを表示したかったので調査した結果、swiperってライブラリが良さそうだったので、使ってみた。

公式サイト

swiperjs.com

実装内容・説明

Typescript使っているので、それに合わせて実装
jsの情報はいっぱい出てきたけど、typescriptは、あんまりなかったので、手探りだった。。。

動きは、全部swiperが付けてくれるので、こっちは、動きの定義とレイアウトの定義をしてあげるだけ。

完成イメージ

趣味全開で作ってるので、ご了承下さい。

html

まずは、見た目側
面倒くさいから、作ったので全部載せる。

<!DOCTYPE html>
<html lang="ja" class="h-100">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <meta name="Description" content="Enter your description here"/>

  <script src="/js/youtube.js"></script>
  <link rel="stylesheet" href="/style.css">
  <link rel="stylesheet" href="/youtube.css">
  <title>GalwWing</title>

</head>
<body class="h-100 bg-light">
<!-- 全ページを囲む要素 -->

<main class="h-100">
  <!-- サイトバーメニュー -->
  <!-- サイトバーメニュー -->

  <!-- 全ページの右のコンテンツ -->
  <div class="page-content main w-100">
    <div id="youtube">
      <div id="player"></div>
    </div>
  </div>

  <!-- Slider main container -->
  <div class="swiper">
    <!-- Additional required wrapper -->
    <div class="swiper-wrapper">
    </div>

    <!-- If we need pagination -->
    <div class="swiper-pagination"></div>

    <!-- If we need navigation buttons -->
    <div class="swiper-button-prev"></div>
    <div class="swiper-button-next"></div>

    <!-- If we need scrollbar -->
    <div class="swiper-scrollbar"></div>
  </div>

</main>
</body>

</html>

重要なのは、<div class="swiper">とその中の定義。
基本的に、公式サイトで乗ってるレイアウトそのまま貼り付ければ、行けるはず。
リストで表示したいデータを、<div class="swiper-wrapper">に追加してやる必要がある。
とりあえず試す場合は、公式サイトに以下のようなサンプルが記載されている

<!-- Slider main container -->
<div class="swiper">
  <!-- Additional required wrapper -->
  <div class="swiper-wrapper">
    <!-- Slides -->
    <div class="swiper-slide">Slide 1</div>
    <div class="swiper-slide">Slide 2</div>
    <div class="swiper-slide">Slide 3</div>
    ...
  </div>
  <!-- If we need pagination -->
  <div class="swiper-pagination"></div>

  <!-- If we need navigation buttons -->
  <div class="swiper-button-prev"></div>
  <div class="swiper-button-next"></div>

  <!-- If we need scrollbar -->
  <div class="swiper-scrollbar"></div>
</div>

typescript

どちらかというと、こっちの実装で苦労した。
webpackが絡んでくると、typescript系の実装は、敷居が10段くらい高くなるんだよね。。。

まずは、npmでモジュールをインストール

npm install swiper

実装しているクラスが、雑音多いので、実装部分だけ抜粋。

// import Swiper styles
import 'swiper/css';
import 'swiper/css/navigation';
import 'swiper/css/pagination';

// コアバージョンに加えて、ナビゲーションとページネーションを追加する
import Swiper, { Navigation, Pagination, SwiperOptions } from 'swiper';

// モジュールを使用可能に
Swiper.use([Navigation, Pagination]);

// 省略

window.onload = () => {
  const swiperParams: SwiperOptions = {
    direction: 'horizontal',
    slidesPerView: 3,
    spaceBetween: 50,
    loop: false,
    autoplay: true,
    pagination: {
      el: '.swiper-pagination',
    },
    navigation: {
      nextEl: '.swiper-button-next',
      prevEl: '.swiper-button-prev',
    },
    scrollbar: {
      el: '.swiper-scrollbar',
    },
  };

  const swiper = new Swiper('.swiper', swiperParams);
};

SwiperOptions で動きを定義。
paginationで、位置情報の「・・・」みたいなやつを表示するタグを指定。
nabigationは、移動するためのボタンを表示するタグを指定。
scrollbarは、なんだっけ。。。?思い出せん。。。
あと、cssのインポートとuseでswiperに使う情報を連携してあげる必要がある。
cssの定義は、webpackに起因してくるので、おまじない程度に考えてもらえればいいはず。

公式サイトだと、directionverticalになっているけど、それだと「・・・」が縦に出てきてしまうので、イメージと違うから、horizontalを指定。

あとは、なんとなくのイメージで分かると思うから、大雑把に説明(今までの説明も大雑把な気がするが。)
slidesPerView:画面に表示するデータ数
spaceBetween:データの感覚 loop:最初と最後の要素に来た際、サイクルさせる。falseにすると、ボタンが非活性になる。
autoplay:動きをちゃんと検証してないけど、たぶん、自動で移動してリストの内容を見せてくれると思う。

Swiperのインスタンス生成するときにオプションとswiperの定義をしているタグを指定することで、完成イメージの表示になる。
ただ、最後の難問として、webpackの定義がいる。

webpack

はっきり言って、typescriptを難しくしている犯人は、webpackだと思っている。
typescriptの環境作れていること前提で話すが、必要な部分はcss-loader付近の定義

const config = {
  module: {
    rules: [
      {
        test: /\.(ts|tsx)$/i,
        loader: 'ts-loader',
        exclude: ['/node_modules/'],
        options: {
          transpileOnly: true,
          configFile: process.argv.mode === 'production' ? 'tsconfig.json' : 'tsconfig.dev.json',
        },
      },
      {
        test: /\.css$/i,
        use: [stylesHandler, { loader: 'css-loader', options: { url: false } }],
        sideEffects: true, // production modeでもswiper-bundle.cssが使えるように
      },
      {
        test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i,
        type: 'asset',
      },

      // Add your rules for custom modules here
      // Learn more about loaders from https://webpack.js.org/loaders/
    ],
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js'],
  },
};

この定義を入れることで、最終的にビルドしたjsに、cssの定義を含めることができるはず。。。
なんとなく、雰囲気で実装してる。たしか、以前調べたときに、そんなだった気がする。
ライブラリにcssが含まれているときに、htmlにnode_moduleのパス書きたくなかったので、この定義をした気がする、全然気にならない人は、typescripでインポートしたファイルへのパスをhtmlで定義してやれば、webpackに書かなくてもイケる気がする。
個人的に、そのやり方は気に食わないが。

参考サイト

雑記

jquery非依存は、探せばあるものだな。
以前に関わったプロジェクトで、jquery起因でパフォーマンスが出ない事例を聞いていたので、なるべく避けるようにしているが、jquery非依存ライブラリの日本語の情報は、まだ少ない気がする。
あとは、定義の仕方で悩むことが多かった。
いろんなのが起因してビルドエラーになっていたり、ビルド忘れていて定義が反映されないから、定義内容を何度も見返したりしていた。
PONに気づくと、アハ体験が起きたあとに、落胆するんだよね。。。
他の人は、どうなんだろう?怒りが湧くのか、笑ってしまうのか、落胆するのか、あるいは、別の反応が起こるのか。

GWは、ホロライブの動画を結構見た気がする。
ホロライブを見ると沼にハマるって意味が分かったわ。。。
きっかけがあると、人間関係が見えてくるようになって、他のホロメンの動画を見てしまい、その連鎖が止まらなくなるんだよね。。。

youtubeのUIが、最近、気に食わないのだが、俺だけ?
あと、チャットがウザいから非表示にしたいんだけど、設定で非表示にできないのかな?
たぶん、あれのせいでパフォーマンス落ちてる気がするんだよね。。。
マシンスペック上げられればいいんだけど、cpu交換って、なんか怖い。

Githubでissueのテンプレートを設定する

調査日付

2022.05.02

やり方

Settingページから、中段くらいにあるfeature/Issueの「Set up template」を押下する

「Add template: select」 から、テンプレを選択して修正する ちなみに、デフォルトで用意されているテンプレの意味

  • Bug report:バグレポート
  • Feature request:機能要望
  • Custome request:カスタマイズ

バグレポート/機能要望以外を追加する場合は、カスタマイズ選んで変えればいい。
バグレポート/機能要望は、フォーマットがある程度準備されているので、欲しいレイアウト次第だと思う。
英語は分かりにくい等あれば、ここで日本語に編集しておけばいい。

追加し終わったら、「Propose changes」で、コミットして、テンプレート変更内容を反映させる。

ちなみに、自分のfeature requestのテンプレート設定

# 概要

# 理由・目的

# 実装方針

## タスク

- [ ] 細かいタスクに分解できているなら書き出す

# 参考

## サイトURL

## 資料

雑記・感想

git使ってると、個人プロジェクトでも、後々、これはどういう意味だっけ?ってなるので、できれば、テンプレートを利用して、情報を整理して書く癖をつけておいた方がいいと最近思った。

まとまった休暇を取れた場合、久々に機能追加してくと、過去の自分が何を書いたのか、全くわからない状態になってしまって、必死に何を書いたか思い出すのに時間がかかったのが悔やまれる。。。
もっと休みを有意義に使いたかった。。。

参考サイト

Githubにissueのテンプレートを作成する方法|Koushi Kagawa|note

【github】issueを複数テンプレート化してissueを整理しよう! | 2055年からきたごんじっち

オレオレ GitHub Issue テンプレートを晒す - ほとラボ

【翻訳・要約】Javascript vs Typescript

参考サイト

dev.to

経緯

typescriptよく使っているので、改めて違いを把握しておきたく読んだ

内容の超要約

  • JavaScriptとは?

  • Typescriptとは?

    • すべてのJavaScriptライブラリおよびフレームワークと互換性あり
    • コードの複雑さが増すにつれて、JavaScriptOOP要件を満たす必要があり、それを書いけするためにTypescriptが開発された
    • コード開発の高速化に役立つ

個人的見解

Typescriptのメリットは、前述してあるとおり、OOPの概念を理解していれば、使いやすい点。
Java触ってたら、学習コストは、幾分か少なくなる。

ただ、パフォーマンス解析するときは、Typescriptだと苦労した経験がある。

あと、互換性があるというが、全部互換があるわけではない。
一部、有名なFWでも、メンテがされてないと、クラス定義ファイルがなくて苦労するケースがあった記憶がある。

ただ、開発が早くなるのは、実感としてある。
クラス定義ファイルをちゃんと作りながら開発すること前提ではあるが、