|
|
@@ -1,4 +1,200 @@
|
|
|
package cn.seecoder.fdroidrepository.Service.ServiceImpl;
|
|
|
|
|
|
+import cn.seecoder.fdroidrepository.DataObject.PO.AppDetailPO;
|
|
|
+import cn.seecoder.fdroidrepository.utils.RedisUtil;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.data.redis.core.RedisTemplate;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.sql.*;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Objects;
|
|
|
+import java.util.concurrent.*;
|
|
|
+
|
|
|
+@Service
|
|
|
public class ApkService {
|
|
|
+
|
|
|
+ private final static String APP_SCORE_RANK="app_score_rank";
|
|
|
+
|
|
|
+ private final static String APP_DOWNLOAD_COUNT_RANK = "app_download_count_rank";
|
|
|
+
|
|
|
+ @Value("$(spring.datasource.url)")
|
|
|
+ private static String JDBC_URL;
|
|
|
+ @Value("$(spring.datasource.username)")
|
|
|
+ private static String JDBC_USER;
|
|
|
+ @Value("$(spring.datasource.password)")
|
|
|
+ private static String JDBC_PASSWORD;
|
|
|
+ @Autowired
|
|
|
+ private RedisTemplate redisTemplate;
|
|
|
+
|
|
|
+ private static ScheduledExecutorService updateExecutorService = Executors.newScheduledThreadPool(1);
|
|
|
+
|
|
|
+ public ApkService(){
|
|
|
+ updateExecutorService.scheduleAtFixedRate(() -> {
|
|
|
+ // update score rank
|
|
|
+ updateScoreRank();
|
|
|
+ // update downloads rank
|
|
|
+ updateDownloadCountRank();
|
|
|
+ }, 1, 2 * 60 * 60, TimeUnit.SECONDS);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void updateScoreRank(){
|
|
|
+ redisTemplate.delete(APP_SCORE_RANK);
|
|
|
+ Map<Integer,Double> rankMap = getScoreRankFromDB();
|
|
|
+ for (Map.Entry<Integer, Double> entry : rankMap.entrySet()) {
|
|
|
+ int appId = entry.getKey();
|
|
|
+ double averageScore = entry.getValue();
|
|
|
+ redisTemplate.opsForZSet().add(APP_SCORE_RANK, RedisUtil.getSoreKey(String.valueOf(appId)), averageScore);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void updateDownloadCountRank(){
|
|
|
+ redisTemplate.delete(APP_DOWNLOAD_COUNT_RANK);
|
|
|
+ Integer maxAppId = getMaxAppId();
|
|
|
+ for(int id =0; id<=maxAppId;id++){
|
|
|
+ String key =RedisUtil.getDownloadCountKey(String.valueOf(id));
|
|
|
+ Integer count = (Integer) redisTemplate.opsForValue().get(key);
|
|
|
+ redisTemplate.opsForZSet().add(APP_DOWNLOAD_COUNT_RANK,key, Objects.isNull(count)?0:count);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public Double getAppScore(Integer appId){
|
|
|
+ return redisTemplate.opsForZSet().score(APP_SCORE_RANK, RedisUtil.getSoreKey(String.valueOf(appId)));
|
|
|
+ }
|
|
|
+
|
|
|
+ public Long getAppDownLoadCount(Integer appId){
|
|
|
+ double count = redisTemplate.opsForZSet().score(APP_DOWNLOAD_COUNT_RANK,RedisUtil.getDownloadCountKey(String.valueOf(appId)));
|
|
|
+ return (long) count;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<Integer/* appId */,Double/* score */> getScoreRankFromDB(){
|
|
|
+ Map<Integer,Double> res =new HashMap<>();
|
|
|
+ try (Connection connection = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD);
|
|
|
+ Statement statement = connection.createStatement();
|
|
|
+ ResultSet resultSet = statement.executeQuery("SELECT app_id, AVG(score) as average_score FROM app_score")) {
|
|
|
+ while (resultSet.next()) {
|
|
|
+ int appId = resultSet.getInt("app_id");
|
|
|
+ double averageScore = resultSet.getDouble("average_score");
|
|
|
+ res.put(appId,averageScore);
|
|
|
+ }
|
|
|
+ } catch (SQLException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ public AppDetailPO getAppDetailPO(Integer appId) {
|
|
|
+ try (Connection connection = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD);
|
|
|
+ PreparedStatement preparedStatement = connection.prepareStatement(
|
|
|
+ "SELECT * FROM app_detail WHERE id = ?"
|
|
|
+ )) {
|
|
|
+ preparedStatement.setString(1, String.valueOf(appId));
|
|
|
+
|
|
|
+ try (ResultSet resultSet = preparedStatement.executeQuery()) {
|
|
|
+ AppDetailPO appDetailPO = new AppDetailPO();
|
|
|
+ appDetailPO.setAppId(resultSet.getInt("id"));
|
|
|
+ appDetailPO.setAppName(resultSet.getString("app_name"));
|
|
|
+ appDetailPO.setAppLogoSrc(resultSet.getString("img_src"));
|
|
|
+ appDetailPO.setBrief(resultSet.getString("brief"));
|
|
|
+ appDetailPO.setDescription(resultSet.getString("package_description"));
|
|
|
+ return appDetailPO;
|
|
|
+ }
|
|
|
+ } catch (SQLException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void addDownloadCount(Integer appId) {
|
|
|
+ String key = RedisUtil.getDownloadCountKey(String.valueOf(appId));
|
|
|
+ redisTemplate.opsForValue().increment(key);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public void addAppScore(Integer appId, long userId, Integer score) {
|
|
|
+ if (isScoreExists(appId, userId)) {
|
|
|
+ // if the user has scored, update it
|
|
|
+ updateAppScore(appId, userId, score);
|
|
|
+ } else {
|
|
|
+ // insert
|
|
|
+ insertAppScore(appId, userId, score);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isScoreExists(Integer appId, long userId) {
|
|
|
+ try (Connection connection = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD);
|
|
|
+ PreparedStatement preparedStatement = connection.prepareStatement(
|
|
|
+ "SELECT COUNT(*) FROM app_score WHERE app_id = ? AND user_id = ?"
|
|
|
+ )) {
|
|
|
+
|
|
|
+ preparedStatement.setInt(1, appId);
|
|
|
+ preparedStatement.setLong(2, userId);
|
|
|
+
|
|
|
+ try (ResultSet resultSet = preparedStatement.executeQuery()) {
|
|
|
+ if (resultSet.next()) {
|
|
|
+ return resultSet.getInt(1) > 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (SQLException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void updateAppScore(Integer appId, long userId, Integer score) {
|
|
|
+ try (Connection connection = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD);
|
|
|
+ PreparedStatement preparedStatement = connection.prepareStatement(
|
|
|
+ "UPDATE app_score SET score = ? WHERE app_id = ? AND user_id = ?"
|
|
|
+ )) {
|
|
|
+
|
|
|
+ preparedStatement.setInt(1, score);
|
|
|
+ preparedStatement.setInt(2, appId);
|
|
|
+ preparedStatement.setLong(3, userId);
|
|
|
+
|
|
|
+ preparedStatement.executeUpdate();
|
|
|
+
|
|
|
+ } catch (SQLException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void insertAppScore(Integer appId, long userId, Integer score) {
|
|
|
+ try (Connection connection = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD);
|
|
|
+ PreparedStatement preparedStatement = connection.prepareStatement(
|
|
|
+ "INSERT INTO app_score (app_id, user_id, score) VALUES (?, ?, ?)"
|
|
|
+ )) {
|
|
|
+
|
|
|
+ preparedStatement.setInt(1, appId);
|
|
|
+ preparedStatement.setLong(2, userId);
|
|
|
+ preparedStatement.setInt(3, score);
|
|
|
+
|
|
|
+ preparedStatement.executeUpdate();
|
|
|
+
|
|
|
+ } catch (SQLException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private Integer getMaxAppId(){
|
|
|
+ try (Connection connection = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD);
|
|
|
+ Statement statement = connection.createStatement();
|
|
|
+ ResultSet resultSet = statement.executeQuery("SELECT MAX(id) FROM app_detail")) {
|
|
|
+
|
|
|
+ if (resultSet.next()) {
|
|
|
+ int maxId = resultSet.getInt(1);
|
|
|
+ return maxId;
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (SQLException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
}
|