From e44a1df22e1bb178f77486c40d05f32b7a4803de Mon Sep 17 00:00:00 2001 From: hrj Date: Mon, 28 Feb 2022 00:00:40 +0530 Subject: [PATCH 1/3] select random captchas Signed-off-by: hrj --- src/main/scala/lc/core/captchaManager.scala | 19 +++++++++++++++++++ src/main/scala/lc/database/statements.scala | 15 ++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/main/scala/lc/core/captchaManager.scala b/src/main/scala/lc/core/captchaManager.scala index 290c95f..8d41cf7 100644 --- a/src/main/scala/lc/core/captchaManager.scala +++ b/src/main/scala/lc/core/captchaManager.scala @@ -105,16 +105,35 @@ class CaptchaManager(config: Config, captchaProviders: CaptchaProviders) { } } + private def getCount(param: Parameters): Option[Int] = { + val countPstmt = Statements.tlStmts.get.countPstmt + countPstmt.setString(1, param.level) + countPstmt.setString(2, param.media) + countPstmt.setString(3, param.input_type) + val rs = countPstmt.executeQuery() + if (rs.next()) { + Some(rs.getInt("count")) + } else { + None + } + } + private def getToken(param: Parameters): Option[Int] = { + val count = getCount(param).getOrElse(0) + if (count == 0) { + None + } else { val tokenPstmt = Statements.tlStmts.get.tokenPstmt tokenPstmt.setString(1, param.level) tokenPstmt.setString(2, param.media) tokenPstmt.setString(3, param.input_type) + tokenPstmt.setInt(4, count) val rs = tokenPstmt.executeQuery() if (rs.next()) { Some(rs.getInt("token")) } else { None + } } } diff --git a/src/main/scala/lc/database/statements.scala b/src/main/scala/lc/database/statements.scala index 3867d80..b1b7a0f 100644 --- a/src/main/scala/lc/database/statements.scala +++ b/src/main/scala/lc/database/statements.scala @@ -70,6 +70,17 @@ class Statements(dbConn: DBConn, maxAttempts: Int) { "WHERE token = ?;" ) + val countPstmt: PreparedStatement = dbConn.con.prepareStatement( + s""" + SELECT count(*) as count + FROM challenge + WHERE attempted < $maxAttempts AND + contentLevel = ? AND + contentType = ? AND + contentInput = ? + """ + ) + val tokenPstmt: PreparedStatement = dbConn.con.prepareStatement( s""" SELECT token, attempted @@ -78,7 +89,9 @@ class Statements(dbConn: DBConn, maxAttempts: Int) { contentLevel = ? AND contentType = ? AND contentInput = ? - ORDER BY attempted ASC LIMIT 1""" + LIMIT 1 + OFFSET FLOOR(RAND()*?) + """ ) val deleteAnswerPstmt: PreparedStatement = dbConn.con.prepareStatement( From 8316084ee7cd892d9f175667a9365cd05331d353 Mon Sep 17 00:00:00 2001 From: hrj Date: Mon, 28 Feb 2022 00:17:13 +0530 Subject: [PATCH 2/3] create equal number of captchas for each parameter combination in background task Signed-off-by: hrj --- src/main/scala/lc/background/taskThread.scala | 31 +++++++++++++------ src/main/scala/lc/core/captchaManager.scala | 22 ++++++------- src/main/scala/lc/database/statements.scala | 2 +- 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/main/scala/lc/background/taskThread.scala b/src/main/scala/lc/background/taskThread.scala index 6df95a5..bc23d9f 100644 --- a/src/main/scala/lc/background/taskThread.scala +++ b/src/main/scala/lc/background/taskThread.scala @@ -18,22 +18,33 @@ class BackgroundTask(config: Config, captchaManager: CaptchaManager) { val challengeGCPstmt = Statements.tlStmts.get.challengeGCPstmt challengeGCPstmt.executeUpdate() - val imageNumResult = Statements.tlStmts.get.getCountChallengeTable.executeQuery() - val imageNum = if (imageNumResult.next()) { - imageNumResult.getInt("total") - } else { - 0 - } + for (param <- allParameterCombinations()) { + val imageNum = captchaManager.getCount(param).getOrElse(0) + val countCreate = (config.throttle * 1.1).toInt - imageNum + if (countCreate > 0) { + println(s"Creating $countCreate captchas for $param") - val throttle = (config.throttle * 1.1).toInt - imageNum - - for (i <- 0 until throttle) { - captchaManager.generateChallenge(getRandomParam()) + for (i <- 0 until countCreate) { + captchaManager.generateChallenge(param) + } + } } } catch { case exception: Exception => println(exception) } } } + private def allParameterCombinations(): List[Parameters] = { + (config.captchaConfig).flatMap {captcha => + (captcha.allowedLevels).flatMap {level => + (captcha.allowedMedia).flatMap {media => + (captcha.allowedInputType).map {inputType => + Parameters(level, media, inputType, Some(Size(0, 0))) + } + } + } + } + } + private def getRandomParam(): Parameters = { val captcha = pickRandom(config.captchaConfig) val level = pickRandom(captcha.allowedLevels) diff --git a/src/main/scala/lc/core/captchaManager.scala b/src/main/scala/lc/core/captchaManager.scala index 8d41cf7..b1cd177 100644 --- a/src/main/scala/lc/core/captchaManager.scala +++ b/src/main/scala/lc/core/captchaManager.scala @@ -105,8 +105,8 @@ class CaptchaManager(config: Config, captchaProviders: CaptchaProviders) { } } - private def getCount(param: Parameters): Option[Int] = { - val countPstmt = Statements.tlStmts.get.countPstmt + def getCount(param: Parameters): Option[Int] = { + val countPstmt = Statements.tlStmts.get.countForParameterPstmt countPstmt.setString(1, param.level) countPstmt.setString(2, param.media) countPstmt.setString(3, param.input_type) @@ -123,16 +123,16 @@ class CaptchaManager(config: Config, captchaProviders: CaptchaProviders) { if (count == 0) { None } else { - val tokenPstmt = Statements.tlStmts.get.tokenPstmt - tokenPstmt.setString(1, param.level) - tokenPstmt.setString(2, param.media) - tokenPstmt.setString(3, param.input_type) + val tokenPstmt = Statements.tlStmts.get.tokenPstmt + tokenPstmt.setString(1, param.level) + tokenPstmt.setString(2, param.media) + tokenPstmt.setString(3, param.input_type) tokenPstmt.setInt(4, count) - val rs = tokenPstmt.executeQuery() - if (rs.next()) { - Some(rs.getInt("token")) - } else { - None + val rs = tokenPstmt.executeQuery() + if (rs.next()) { + Some(rs.getInt("token")) + } else { + None } } } diff --git a/src/main/scala/lc/database/statements.scala b/src/main/scala/lc/database/statements.scala index b1b7a0f..262d9be 100644 --- a/src/main/scala/lc/database/statements.scala +++ b/src/main/scala/lc/database/statements.scala @@ -70,7 +70,7 @@ class Statements(dbConn: DBConn, maxAttempts: Int) { "WHERE token = ?;" ) - val countPstmt: PreparedStatement = dbConn.con.prepareStatement( + val countForParameterPstmt: PreparedStatement = dbConn.con.prepareStatement( s""" SELECT count(*) as count FROM challenge From cb0c2447799e345555f11f74dbc8d4780eb90e2c Mon Sep 17 00:00:00 2001 From: hrj Date: Mon, 28 Feb 2022 09:30:31 +0530 Subject: [PATCH 3/3] in background task, divide total required by number of combinations, and create in multiple iterations Signed-off-by: hrj --- src/main/scala/lc/background/taskThread.scala | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/scala/lc/background/taskThread.scala b/src/main/scala/lc/background/taskThread.scala index bc23d9f..c7f59ce 100644 --- a/src/main/scala/lc/background/taskThread.scala +++ b/src/main/scala/lc/background/taskThread.scala @@ -18,11 +18,15 @@ class BackgroundTask(config: Config, captchaManager: CaptchaManager) { val challengeGCPstmt = Statements.tlStmts.get.challengeGCPstmt challengeGCPstmt.executeUpdate() - for (param <- allParameterCombinations()) { - val imageNum = captchaManager.getCount(param).getOrElse(0) - val countCreate = (config.throttle * 1.1).toInt - imageNum - if (countCreate > 0) { - println(s"Creating $countCreate captchas for $param") + val allCombinations = allParameterCombinations() + val requiredCountPerCombination = Math.max(1, (config.throttle * 1.01) / allCombinations.size).toInt + + for (param <- allCombinations) { + val countExisting = captchaManager.getCount(param).getOrElse(0) + val countRequired = requiredCountPerCombination - countExisting + if (countRequired > 0) { + val countCreate = Math.min(1.0 + requiredCountPerCombination/10.0, countRequired).toInt + println(s"Creating $countCreate of $countRequired captchas for $param") for (i <- 0 until countCreate) { captchaManager.generateChallenge(param)