From 82903fde47c2275b2af9540d49e2331ad0c1459d Mon Sep 17 00:00:00 2001 From: Jonathan Williams Date: Wed, 13 May 2015 00:00:37 -0700 Subject: [PATCH] Updates for task conversion. --- .../mineplex/chestConverter/AccountTask.java | 7 + .../chestConverter/AsyncJsonWebCall.java | 63 +++ .../chestConverter/ChestConverter.java | 32 +- .../ChestConverterRepository.java | 240 ++-------- .../mineplex/chestConverter/JsonWebCall.java | 359 ++++++++++++++ .../mineplex/chestConverter/SearchConf.java | 13 + Website/LOC.Core/LOC.Core.csproj | 1 + Website/LOC.Core/SearchConf.cs | 13 + .../Models/AccountAdministrator.cs | 4 +- .../Models/IAccountAdministrator.cs | 3 +- .../Controllers/PlayerAccountController.cs | 5 +- .../LOC.Website.Web.Publish.xml | 444 +++++++++--------- Website/LOCWebsite.suo | Bin 474624 -> 474624 bytes 13 files changed, 757 insertions(+), 427 deletions(-) create mode 100644 Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/AccountTask.java create mode 100644 Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/AsyncJsonWebCall.java create mode 100644 Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/JsonWebCall.java create mode 100644 Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/SearchConf.java create mode 100644 Website/LOC.Core/SearchConf.cs diff --git a/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/AccountTask.java b/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/AccountTask.java new file mode 100644 index 000000000..f9433b184 --- /dev/null +++ b/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/AccountTask.java @@ -0,0 +1,7 @@ +package mineplex.chestConverter; + +public class AccountTask +{ + public String Task; + public String UUID; +} diff --git a/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/AsyncJsonWebCall.java b/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/AsyncJsonWebCall.java new file mode 100644 index 000000000..63e3812e3 --- /dev/null +++ b/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/AsyncJsonWebCall.java @@ -0,0 +1,63 @@ +package mineplex.chestConverter; + +import mineplex.core.common.util.Callback; + +public class AsyncJsonWebCall extends JsonWebCall +{ + public AsyncJsonWebCall(String url) + { + super(url); + } + + public void Execute() + { + Thread asyncThread = new Thread(new Runnable() + { + public void run() + { + AsyncJsonWebCall.super.Execute(); + } + }); + + asyncThread.start(); + } + + public void Execute(final Object argument) + { + Thread asyncThread = new Thread(new Runnable() + { + public void run() + { + AsyncJsonWebCall.super.Execute(argument); + } + }); + + asyncThread.start(); + } + + public void Execute(final Class callbackClass, final Callback callback) + { + Thread asyncThread = new Thread(new Runnable() + { + public void run() + { + AsyncJsonWebCall.super.Execute(callbackClass, callback); + } + }); + + asyncThread.start(); + } + + public void Execute(final Class callbackClass, final Callback callback, final Object argument) + { + Thread asyncThread = new Thread(new Runnable() + { + public void run() + { + AsyncJsonWebCall.super.Execute(callbackClass, callback, argument); + } + }); + + asyncThread.start(); + } +} diff --git a/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/ChestConverter.java b/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/ChestConverter.java index a9ddea664..98be01049 100644 --- a/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/ChestConverter.java +++ b/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/ChestConverter.java @@ -1,8 +1,10 @@ package mineplex.chestConverter; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.logging.Logger; public class ChestConverter @@ -13,29 +15,41 @@ public class ChestConverter public static void main (String args[]) { _repository = new ChestConverterRepository(); - int count = 5000; + int count = 0; + int batchAmount = 5000; + + HashMap tasks = _repository.getTaskList(); while (true) { long time = System.currentTimeMillis(); - HashMap playerMap = _repository.retrieveKeyInventoryBatch(count); + HashMap> playerMap = new HashMap>(); - if (playerMap.size() == 0) + + List taskList = _repository.getTasks(count, batchAmount); + + if (taskList.size() == 0) return; - _repository.incrementClient(playerMap, false); - _repository.deleteKeys(count); + for (AccountTask task : taskList) + { + if (!playerMap.containsKey(task.UUID)) + playerMap.put(task.UUID, new ArrayList()); + + playerMap.get(task.UUID).add(tasks.get(task.Task)); + } + + _repository.incrementClients(playerMap); try { - log("Natural sleep. " + count + " took " + (System.currentTimeMillis() - time) / 1000 + " seconds."); - Thread.sleep(250); + count += batchAmount; + log("Natural sleep. " + batchAmount + " took " + (System.currentTimeMillis() - time) / 1000 + " seconds. Count = " + + count); + Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } - - break; } } diff --git a/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/ChestConverterRepository.java b/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/ChestConverterRepository.java index 0970b1b4e..302a6ef0e 100644 --- a/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/ChestConverterRepository.java +++ b/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/ChestConverterRepository.java @@ -5,23 +5,20 @@ import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map.Entry; public class ChestConverterRepository { - private String _connectionString = "jdbc:mysql://db.mineplex.com:3306/Account"; + private String _connectionString = "jdbc:mysql://db.mineplex.com:3306/Account?allowMultiQueries=true"; private String _userName = "root"; private String _password = "tAbechAk3wR7tuTh"; - private static String RETRIEVE_CHESTS = "SELECT A.uuid, count FROM accountInventory INNER JOIN accounts AS A ON A.id = accountInventory.accountId WHERE itemId = 56 AND count > 0 ORDER BY accountInventory.id LIMIT ?;"; - private static String RETRIEVE_KEYS = "SELECT A.uuid, count FROM accountInventory INNER JOIN accounts AS A ON A.id = accountInventory.accountId WHERE itemId = 67 AND count > 0 ORDER BY accountInventory.id LIMIT ?;"; - - private static String DELETE_CHESTS = "DELETE FROM accountInventory WHERE itemId = 56 ORDER BY accountInventory.id LIMIT ?"; - private static String DELETE_KEYS = "DELETE FROM accountInventory WHERE itemId = 67 ORDER BY accountInventory.id LIMIT ?"; - - private static String INSERT_CLIENT_INVENTORY = "INSERT INTO accountInventory (accountId, itemId, count) SELECT accounts.id, ?, ? FROM accounts WHERE accounts.uuid = ? ON DUPLICATE KEY UPDATE count=count + VALUES(count);"; - private static String UPDATE_CLIENT_INVENTORY = "UPDATE accountInventory AS AI INNER JOIN accounts ON AI.accountId = accounts.id SET AI.count = AI.count + ? WHERE accounts.uuid = ? AND AI.itemId = ?;"; + private static String ADD_ACCOUNT_TASK = "INSERT INTO accountTasks (accountId, taskId) VALUES (?, ?);"; + private static String RETRIEVE_TASKS = "SELECT id, name FROM tasks;"; private static Connection _connection; @@ -56,24 +53,24 @@ public class ChestConverterRepository } } - public HashMap retrieveChestInventoryBatch(int count) + public HashMap getTaskList() { - HashMap playerList = new HashMap(); - + HashMap tasks = new HashMap(); PreparedStatement preparedStatement = null; try { if (_connection == null || _connection.isClosed()) _connection = DriverManager.getConnection(_connectionString, _userName, _password); + + preparedStatement = _connection.prepareStatement(RETRIEVE_TASKS); + preparedStatement.execute(); - preparedStatement = _connection.prepareStatement(RETRIEVE_CHESTS); - preparedStatement.setInt(1, count); - ResultSet resultSet = preparedStatement.executeQuery(); + ResultSet resultSet = preparedStatement.getResultSet(); while (resultSet.next()) { - playerList.put(resultSet.getString(1), resultSet.getInt(2)); + tasks.put(resultSet.getString(2), resultSet.getInt(1)); } } catch (Exception exception) @@ -95,133 +92,64 @@ public class ChestConverterRepository } } - return playerList; + return tasks; } - public HashMap retrieveKeyInventoryBatch(int count) + public List getTasks(int skip, int count) + { + return new JsonWebCall("http://accounts.mineplex.com/PlayerAccount/GetTasksByCount").Execute(new com.google.gson.reflect.TypeToken>(){}.getType(), new SearchConf(skip, count)); + } + + public void incrementClients(HashMap> playerList) { - HashMap playerList = new HashMap(); - PreparedStatement preparedStatement = null; + Statement statement = null; try { if (_connection == null || _connection.isClosed()) _connection = DriverManager.getConnection(_connectionString, _userName, _password); - preparedStatement = _connection.prepareStatement(RETRIEVE_KEYS); - preparedStatement.setInt(1, count); - ResultSet resultSet = preparedStatement.executeQuery(); - - while (resultSet.next()) + statement = _connection.createStatement(); + HashMap> playerIdList = new HashMap>(); + String queryString = ""; + for (Entry> entry : playerList.entrySet()) { - playerList.put(resultSet.getString(1), resultSet.getInt(2)); + queryString += "SELECT id FROM accounts WHERE accounts.uuid = '" + entry.getKey() + "' LIMIT 1;"; } - } - catch (Exception exception) - { - exception.printStackTrace(); - } - finally - { - if (preparedStatement != null) + + statement.execute(queryString); + statement.getUpdateCount(); + + for (Entry> entry : playerList.entrySet()) { - try + ResultSet resultSet = statement.getResultSet(); + + while (resultSet.next()) { - preparedStatement.close(); - } - catch (SQLException e) - { - e.printStackTrace(); + for (Integer taskId : entry.getValue()) + { + if (!playerIdList.containsKey(resultSet.getInt(1))) + playerIdList.put(resultSet.getInt(1), new ArrayList()); + + playerIdList.get(resultSet.getInt(1)).add(taskId); + } } + statement.getMoreResults(); } - } - - return playerList; - } - - public void incrementClient(HashMap playerList, boolean chest) - { - PreparedStatement preparedStatement = null; - - try - { - if (_connection == null || _connection.isClosed()) - _connection = DriverManager.getConnection(_connectionString, _userName, _password); - preparedStatement = _connection.prepareStatement(UPDATE_CLIENT_INVENTORY); - - for (Entry entry : playerList.entrySet()) + preparedStatement = _connection.prepareStatement(ADD_ACCOUNT_TASK); + System.out.println("adding to mysql db."); + for (Entry> entry : playerIdList.entrySet()) { - preparedStatement.setInt(1, entry.getValue()); - preparedStatement.setString(2, entry.getKey()); - preparedStatement.setInt(3, chest ? 690 : 692); - - preparedStatement.addBatch(); - - if (chest) + for (Integer taskId : entry.getValue()) { - if (entry.getValue() > 20) - { - preparedStatement.setInt(1, 1); - preparedStatement.setString(2, entry.getKey()); - preparedStatement.setInt(3, 692); - - preparedStatement.addBatch(); - } - - if (entry.getValue() > 50) - { - preparedStatement.setInt(1, 1); - preparedStatement.setString(2, entry.getKey()); - preparedStatement.setInt(3, 691); - - preparedStatement.addBatch(); - } + preparedStatement.setInt(1, entry.getKey()); + preparedStatement.setInt(2, taskId); + preparedStatement.addBatch(); } } - int[] rowsAffected = preparedStatement.executeBatch(); - int i = 0; - - preparedStatement.close(); - preparedStatement = _connection.prepareStatement(INSERT_CLIENT_INVENTORY); - - for (Entry entry : playerList.entrySet()) - { - if (rowsAffected[i] < 1) - { - preparedStatement.setInt(1, chest ? 690 : 692); - preparedStatement.setInt(2, entry.getValue()); - preparedStatement.setString(3, entry.getKey()); - - preparedStatement.addBatch(); - - if (chest) - { - if (entry.getValue() > 20) - { - preparedStatement.setInt(1, 692); - preparedStatement.setInt(2, 1); - preparedStatement.setString(3, entry.getKey()); - - preparedStatement.addBatch(); - } - - if (entry.getValue() > 50) - { - preparedStatement.setInt(1, 691); - preparedStatement.setInt(2, 1); - preparedStatement.setString(3, entry.getKey()); - - preparedStatement.addBatch(); - } - } - } - - i++; - } - preparedStatement.executeBatch(); } catch (Exception exception) @@ -243,74 +171,4 @@ public class ChestConverterRepository } } } - - public void deleteChests(int count) - { - PreparedStatement preparedStatement = null; - - try - { - if (_connection == null || _connection.isClosed()) - _connection = DriverManager.getConnection(_connectionString, _userName, _password); - - preparedStatement = _connection.prepareStatement(DELETE_CHESTS); - preparedStatement.setInt(1, count); - preparedStatement.executeUpdate(); - - System.out.println("Deleting " + count + " inventory records."); - } - catch (Exception exception) - { - exception.printStackTrace(); - } - finally - { - if (preparedStatement != null) - { - try - { - preparedStatement.close(); - } - catch (SQLException e) - { - e.printStackTrace(); - } - } - } - } - - public void deleteKeys(int count) - { - PreparedStatement preparedStatement = null; - - try - { - if (_connection == null || _connection.isClosed()) - _connection = DriverManager.getConnection(_connectionString, _userName, _password); - - preparedStatement = _connection.prepareStatement(DELETE_KEYS); - preparedStatement.setInt(1, count); - preparedStatement.executeUpdate(); - - System.out.println("Deleting " + count + " inventory records."); - } - catch (Exception exception) - { - exception.printStackTrace(); - } - finally - { - if (preparedStatement != null) - { - try - { - preparedStatement.close(); - } - catch (SQLException e) - { - e.printStackTrace(); - } - } - } - } } diff --git a/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/JsonWebCall.java b/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/JsonWebCall.java new file mode 100644 index 000000000..b16829d57 --- /dev/null +++ b/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/JsonWebCall.java @@ -0,0 +1,359 @@ +package mineplex.chestConverter; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.Type; + +import mineplex.core.common.util.Callback; +import mineplex.core.common.util.UtilSystem; + +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.conn.scheme.PlainSocketFactory; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.scheme.SchemeRegistry; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.impl.conn.PoolingClientConnectionManager; +import org.apache.http.message.BasicHeader; +import org.apache.http.protocol.HTTP; + +import com.google.gson.Gson; + +public class JsonWebCall +{ + private String _url; + private PoolingClientConnectionManager _connectionManager; + + public JsonWebCall(String url) + { + _url = url; + + SchemeRegistry schemeRegistry = new SchemeRegistry(); + schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory())); + + _connectionManager = new PoolingClientConnectionManager(schemeRegistry); + _connectionManager.setMaxTotal(200); + _connectionManager.setDefaultMaxPerRoute(20); + } + + public String ExecuteReturnStream(Object argument) + { + HttpClient httpClient = new DefaultHttpClient(_connectionManager); + InputStream in = null; + String result = null; + + try + { + HttpResponse response; + + Gson gson = new Gson(); + HttpPost request = new HttpPost(_url); + + if (argument != null) + { + StringEntity params = new StringEntity(gson.toJson(argument)); + params.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json")); + request.setEntity(params); + } + + response = httpClient.execute(request); + + if (response != null) + { + in = response.getEntity().getContent(); + result = convertStreamToString(in); + } + } + catch (Exception ex) + { + System.out.println("Error executing JsonWebCall: \n" + ex.getMessage()); + System.out.println("Result: \n" + result); + + for (StackTraceElement trace : ex.getStackTrace()) + { + System.out.println(trace); + } + } + finally + { + httpClient.getConnectionManager().shutdown(); + + if (in != null) + { + try + { + in.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } + + return result; + } + + public void Execute() + { + Execute((Object)null); + } + + public void Execute(Object argument) + { + HttpClient httpClient = new DefaultHttpClient(_connectionManager); + InputStream in = null; + + try + { + Gson gson = new Gson(); + HttpPost request = new HttpPost(_url); + + if (argument != null) + { + StringEntity params = new StringEntity(gson.toJson(argument)); + params.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json")); + request.setEntity(params); + } + + httpClient.execute(request); + } + catch (Exception ex) + { + System.out.println("JsonWebCall.Execute() Error:\n" + ex.getMessage()); + + for (StackTraceElement trace : ex.getStackTrace()) + { + System.out.println(trace); + } + } + finally + { + httpClient.getConnectionManager().shutdown(); + + if (in != null) + { + try + { + in.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } + } + + public T Execute(Class returnClass) + { + return Execute(returnClass, (Object)null); + } + + public T Execute(Type returnType, Object argument) + { + HttpClient httpClient = new DefaultHttpClient(_connectionManager); + InputStream in = null; + T returnData = null; + String result = null; + + try + { + HttpResponse response; + + Gson gson = new Gson(); + HttpPost request = new HttpPost(_url); + + if (argument != null) + { + StringEntity params = new StringEntity(gson.toJson(argument)); + params.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json")); + request.setEntity(params); + } + + response = httpClient.execute(request); + + if (response != null) + { + in = response.getEntity().getContent(); + + result = convertStreamToString(in); + returnData = new Gson().fromJson(result, returnType); + } + } + catch (Exception ex) + { + System.out.println("Error executing JsonWebCall: \n" + ex.getMessage()); + System.out.println("Result: \n" + result); + + for (StackTraceElement trace : ex.getStackTrace()) + { + System.out.println(trace); + } + } + finally + { + httpClient.getConnectionManager().shutdown(); + + if (in != null) + { + try + { + in.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } + + return returnData; + } + + public T Execute(Class returnClass, Object argument) + { + HttpClient httpClient = new DefaultHttpClient(_connectionManager); + InputStream in = null; + T returnData = null; + String result = null; + + try + { + HttpResponse response; + + Gson gson = new Gson(); + HttpPost request = new HttpPost(_url); + + if (argument != null) + { + StringEntity params = new StringEntity(gson.toJson(argument)); + params.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json")); + request.setEntity(params); + } + + response = httpClient.execute(request); + + if (response != null) + { + in = response.getEntity().getContent(); + + result = convertStreamToString(in); + returnData = new Gson().fromJson(result, returnClass); + } + } + catch (Exception ex) + { + System.out.println("Error executing JsonWebCall: \n" + ex.getMessage()); + System.out.println("Result: \n" + result); + + for (StackTraceElement trace : ex.getStackTrace()) + { + System.out.println(trace); + } + } + finally + { + httpClient.getConnectionManager().shutdown(); + + if (in != null) + { + try + { + in.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } + + return returnData; + } + + public void Execute(Class callbackClass, Callback callback) + { + Execute(callbackClass, callback, (Object)null); + } + + public void Execute(Class callbackClass, Callback callback, Object argument) + { + HttpClient httpClient = new DefaultHttpClient(_connectionManager); + InputStream in = null; + String result = null; + + try + { + HttpResponse response; + + Gson gson = new Gson(); + HttpPost request = new HttpPost(_url); + + if (argument != null) + { + StringEntity params = new StringEntity(gson.toJson(argument)); + params.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json")); + request.setEntity(params); + } + + response = httpClient.execute(request); + + if (response != null && callback != null) + { + in = response.getEntity().getContent(); + + result = convertStreamToString(in); + callback.run(new Gson().fromJson(result, callbackClass)); + } + } + catch (Exception ex) + { + System.out.println("Error executing JsonWebCall: \n" + ex.getMessage()); + UtilSystem.printStackTrace(ex.getStackTrace()); + System.out.println("Result: \n" + result); + } + finally + { + httpClient.getConnectionManager().shutdown(); + + if (in != null) + { + try + { + in.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } + } + + protected String convertStreamToString(InputStream is) + { + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + StringBuilder sb = new StringBuilder(); + + String line = null; + try { + while ((line = reader.readLine()) != null) { + sb.append(line + "\n"); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return sb.toString(); + } +} diff --git a/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/SearchConf.java b/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/SearchConf.java new file mode 100644 index 000000000..36c80fa46 --- /dev/null +++ b/Plugins/Mineplex.ChestConverter/src/mineplex/chestConverter/SearchConf.java @@ -0,0 +1,13 @@ +package mineplex.chestConverter; + +public class SearchConf +{ + public SearchConf(int skip, int count) + { + Skip = skip; + Count = count; + } + + public int Skip; + public int Count; +} diff --git a/Website/LOC.Core/LOC.Core.csproj b/Website/LOC.Core/LOC.Core.csproj index a52e4b798..c4601f0a9 100644 --- a/Website/LOC.Core/LOC.Core.csproj +++ b/Website/LOC.Core/LOC.Core.csproj @@ -76,6 +76,7 @@ + diff --git a/Website/LOC.Core/SearchConf.cs b/Website/LOC.Core/SearchConf.cs new file mode 100644 index 000000000..b6489ca78 --- /dev/null +++ b/Website/LOC.Core/SearchConf.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace LOC.Core +{ + public class SearchConf + { + public int Skip { get; set; } + public int Count { get; set; } + } +} diff --git a/Website/LOC.Website.Common/Models/AccountAdministrator.cs b/Website/LOC.Website.Common/Models/AccountAdministrator.cs index 8d0c23f74..9d7bbd417 100644 --- a/Website/LOC.Website.Common/Models/AccountAdministrator.cs +++ b/Website/LOC.Website.Common/Models/AccountAdministrator.cs @@ -72,13 +72,13 @@ return accounts; } - public List GetTasksByCount(int count) + public List GetTasksByCount(SearchConf searchConf) { var tasks = new List(); using (var repository = _repositoryFactory.CreateRepository()) { - var gameTasks = repository.GetAll().OrderBy(x => x.GameTaskId).Take(count).Include(x => x.Account).ToList(); + var gameTasks = repository.GetAll().OrderBy(x => x.GameTaskId).Skip(searchConf.Skip).Take(searchConf.Count).Include(x => x.Account).ToList(); foreach (var task in gameTasks) { diff --git a/Website/LOC.Website.Common/Models/IAccountAdministrator.cs b/Website/LOC.Website.Common/Models/IAccountAdministrator.cs index afcb11d4e..1e6a1522f 100644 --- a/Website/LOC.Website.Common/Models/IAccountAdministrator.cs +++ b/Website/LOC.Website.Common/Models/IAccountAdministrator.cs @@ -6,6 +6,7 @@ using Core.Model.Sales; using Core.Tokens; using Core.Tokens.Client; + using LOC.Core; public interface IAccountAdministrator { @@ -42,6 +43,6 @@ ClientToken GetAccountByUUID(string uuid); - List GetTasksByCount(int count); + List GetTasksByCount(SearchConf searchConf); } } diff --git a/Website/LOC.Website.Web/Controllers/PlayerAccountController.cs b/Website/LOC.Website.Web/Controllers/PlayerAccountController.cs index 1f6e02b55..fe4efc6a9 100644 --- a/Website/LOC.Website.Web/Controllers/PlayerAccountController.cs +++ b/Website/LOC.Website.Web/Controllers/PlayerAccountController.cs @@ -9,6 +9,7 @@ using Core.Tokens.Client; using Newtonsoft.Json; using System.Collections.Generic; + using LOC.Core; public class PlayerAccountController : Controller { @@ -40,9 +41,9 @@ } [HttpPost] - public ActionResult GetTasksByCount(int count) + public ActionResult GetTasksByCount(SearchConf searchConf) { - var tasks = _accountAdministrator.GetTasksByCount(count); + var tasks = _accountAdministrator.GetTasksByCount(searchConf); var json = JsonConvert.SerializeObject(tasks); return Content(json, "application/json"); diff --git a/Website/LOC.Website.Web/LOC.Website.Web.Publish.xml b/Website/LOC.Website.Web/LOC.Website.Web.Publish.xml index 72e6fb292..4d7cdc038 100644 --- a/Website/LOC.Website.Web/LOC.Website.Web.Publish.xml +++ b/Website/LOC.Website.Web/LOC.Website.Web.Publish.xml @@ -1,12 +1,12 @@  + - @@ -17,8 +17,10 @@ - + + + @@ -26,8 +28,8 @@ - + @@ -41,26 +43,27 @@ - + + + + - + - - - + @@ -71,32 +74,32 @@ - + + - - + - - - + + + - - + + @@ -104,40 +107,41 @@ - - + - + - + - + + + - + - + + - - + @@ -148,53 +152,49 @@ - + - - - - + - - - + + - - + - + - - + + - + + @@ -203,72 +203,74 @@ - - + + - + - + - - + - + - + - + + - + - + - - + + - + - - + + - - + + - + + + @@ -281,40 +283,36 @@ - - - + + - - + - + - - + - @@ -323,8 +321,9 @@ + - + @@ -335,22 +334,21 @@ - - + - - + + @@ -358,6 +356,8 @@ + + @@ -365,17 +365,17 @@ + - + - @@ -383,22 +383,22 @@ + - + - - - + + - + @@ -409,62 +409,64 @@ - + - + + + + + + - - + - + - + - - + - - - + + - + - + @@ -472,66 +474,66 @@ - - + + - + - - + + - - + - - + - - + + - - + + - + - - - - - + + + + + - + + + @@ -542,24 +544,24 @@ - + - - + - + - + + @@ -569,14 +571,13 @@ - + - @@ -586,7 +587,7 @@ - + @@ -597,22 +598,20 @@ - - + + - - - + @@ -620,18 +619,22 @@ + - - + + + - + + + @@ -645,89 +648,87 @@ + - + - + - - - + - - + - + + + + + + - - - + - + - - - + - + - - + - + - + - + @@ -735,66 +736,67 @@ - + - + - - - - + + + - + - + - - + - - + + + - - + + - + - - - - - + + + + + - + + + @@ -805,24 +807,24 @@ - + - - + - + - + + @@ -832,14 +834,13 @@ - + - @@ -849,7 +850,7 @@ - + @@ -860,22 +861,20 @@ - - + + - - - + @@ -883,6 +882,7 @@ + @@ -891,10 +891,13 @@ + - + + + @@ -908,89 +911,87 @@ + - + - + - - - + - - + - + + + + + + - - - - - + - + - - + - + - + - + @@ -998,58 +999,57 @@ - + - + - - + + - - + - - + - - + + + - - + + - + - - - - - + + + + + - + \ No newline at end of file diff --git a/Website/LOCWebsite.suo b/Website/LOCWebsite.suo index 2fd6e5bcf8dbd57713aa32d8462604010f22f6e4..f7fc529703b0807da0c414400d7716a22e1b8ec4 100644 GIT binary patch delta 14218 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 Ee>5#`^Z)<= delta 14531 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

?BpMbt@mXb#ni3^k0bZJ#t2Ft5Il)0 RGK>^4YkJk3&1J^t{}-M@(C`2N