Compare commits
No commits in common. "b65b0c368dcded92db13997860e6fff3e5500b2c" and "0f0c343a853e9387117405e44036ed2c879ff12d" have entirely different histories.
b65b0c368d
...
0f0c343a85
@ -4,7 +4,7 @@
|
|||||||
<component name="FrameworkDetectionExcludesConfiguration">
|
<component name="FrameworkDetectionExcludesConfiguration">
|
||||||
<file type="web" url="file://$PROJECT_DIR$" />
|
<file type="web" url="file://$PROJECT_DIR$" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_19" default="true" project-jdk-name="openjdk-19" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="openjdk-19" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@ -15,7 +15,6 @@ dependencies {
|
|||||||
testImplementation("org.mockito.kotlin:mockito-kotlin:5.0.0")
|
testImplementation("org.mockito.kotlin:mockito-kotlin:5.0.0")
|
||||||
|
|
||||||
implementation("net.java.dev.jna:jna:latest.release")
|
implementation("net.java.dev.jna:jna:latest.release")
|
||||||
implementation(kotlin("reflect"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.test {
|
tasks.test {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import game_logic.runescape.RunescapeRoutines
|
import game_logic.runescape.RunescapeRoutines
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
// RunescapeRoutines.fullRunIncense(0, 158, 348, 0)
|
// RunescapeRoutines.fullRunIncense(0, 4514, 4870, 308)
|
||||||
RunescapeRoutines.processInventoryAtFurnace(2500)
|
RunescapeRoutines.createNecromancyInk(2960)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -29,7 +29,7 @@ interface TemporalController {
|
|||||||
val duration = if(maxAdditionalDuration == 0L){
|
val duration = if(maxAdditionalDuration == 0L){
|
||||||
baseDuration
|
baseDuration
|
||||||
}else{
|
}else{
|
||||||
baseDuration + util.HelperFunctions.getApproximatelyNormalLong(maxAdditionalDuration)
|
baseDuration + util.HelperFunctions.getGaussianLong(maxAdditionalDuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeUnit.MILLISECONDS.sleep(duration)
|
TimeUnit.MILLISECONDS.sleep(duration)
|
||||||
|
|||||||
@ -79,7 +79,7 @@ interface User32 : StdCallLibrary {
|
|||||||
* @param userData Optional user-defined data to pass to the callback.
|
* @param userData Optional user-defined data to pass to the callback.
|
||||||
* @return True if successful, false otherwise.
|
* @return True if successful, false otherwise.
|
||||||
*/
|
*/
|
||||||
fun EnumWindows(lpEnumFunc: StdCallLibrary.StdCallCallback?, userData: Pointer?): Boolean
|
fun EnumWindows(lpEnumFunc: WNDENUMPROC?, userData: Pointer?): Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the title text of the specified window.
|
* Gets the title text of the specified window.
|
||||||
|
|||||||
@ -73,6 +73,13 @@ class RSAgent(override val automaton: Automaton = RobotAutomaton()) : RSOrchestr
|
|||||||
* - Clicks the default "Accept" hotkey to start crafting.
|
* - Clicks the default "Accept" hotkey to start crafting.
|
||||||
* - Waits for the specified crafting duration plus random variance.
|
* - Waits for the specified crafting duration plus random variance.
|
||||||
*
|
*
|
||||||
|
* Usage example:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* val params = StandingTaskParams(...)
|
||||||
|
* orchestrator.processAtBank(params)
|
||||||
|
* ```
|
||||||
|
*
|
||||||
* @param taskParams The [StandingTaskParams] configuring the task details like bank location, hotkeys, and durations.
|
* @param taskParams The [StandingTaskParams] configuring the task details like bank location, hotkeys, and durations.
|
||||||
*/
|
*/
|
||||||
override fun processAtBank(
|
override fun processAtBank(
|
||||||
@ -111,6 +118,12 @@ class RSAgent(override val automaton: Automaton = RobotAutomaton()) : RSOrchestr
|
|||||||
*
|
*
|
||||||
* - Waits for the randomized crafting duration.
|
* - Waits for the randomized crafting duration.
|
||||||
*
|
*
|
||||||
|
* Usage example:
|
||||||
|
* ```
|
||||||
|
* val params = TravelTaskParams(...)
|
||||||
|
* orchestrator.processAtStationNearBank(params)
|
||||||
|
* ```
|
||||||
|
*
|
||||||
* @param taskParams The [TravelTaskParams] configuring the task details.
|
* @param taskParams The [TravelTaskParams] configuring the task details.
|
||||||
*/
|
*/
|
||||||
override fun processAtStationNearBank(
|
override fun processAtStationNearBank(
|
||||||
@ -151,6 +164,17 @@ class RSAgent(override val automaton: Automaton = RobotAutomaton()) : RSOrchestr
|
|||||||
*
|
*
|
||||||
* It then returns the current mouse position as a Point after a slight delay.
|
* It then returns the current mouse position as a Point after a slight delay.
|
||||||
*
|
*
|
||||||
|
* The delay allows the mouse to settle before sampling its position.
|
||||||
|
*
|
||||||
|
* Usage example:
|
||||||
|
* ```
|
||||||
|
* // Get bank location from user mouse position
|
||||||
|
* val bankPoint = orchestrator.getBankPoint()
|
||||||
|
* // Left click the bank to open the interface
|
||||||
|
* orchestrator.automaton.mouseMove(bankPoint)
|
||||||
|
* orchestrator.automaton.mouseClick(InputEvent.BUTTON1_DOWN_MASK)
|
||||||
|
* ```
|
||||||
|
*
|
||||||
* @return The Point position of the mouse after user positions it.
|
* @return The Point position of the mouse after user positions it.
|
||||||
*/
|
*/
|
||||||
override fun getBankPoint(): Point {
|
override fun getBankPoint(): Point {
|
||||||
@ -160,10 +184,19 @@ class RSAgent(override val automaton: Automaton = RobotAutomaton()) : RSOrchestr
|
|||||||
/**
|
/**
|
||||||
* Sleeps for a specified number of game ticks.
|
* Sleeps for a specified number of game ticks.
|
||||||
*
|
*
|
||||||
* A brief random variance is also added to the sleep duration to add some less-robotic behavior.
|
* This method calculates the total sleep duration based on the number of ticks
|
||||||
|
* and the tick duration constant. It then sleeps for that amount plus a small
|
||||||
|
* latency padding.
|
||||||
|
*
|
||||||
|
* A random variance is also added to the sleep duration to add some less-robotic behavior.
|
||||||
|
*
|
||||||
|
* Usage example:
|
||||||
|
* ```
|
||||||
|
* val ticks = 10 // Sleep for 10 game ticks
|
||||||
|
* orchestrator.sleepTicks(ticks)
|
||||||
|
* ```
|
||||||
*
|
*
|
||||||
* @param n The number of game ticks to sleep for.
|
* @param n The number of game ticks to sleep for.
|
||||||
* @see TICK_DURATION_MS
|
|
||||||
*/
|
*/
|
||||||
override fun sleepForNTicks(n: Long) {
|
override fun sleepForNTicks(n: Long) {
|
||||||
val latencyPadding = LATENCY_PADDING_MS
|
val latencyPadding = LATENCY_PADDING_MS
|
||||||
|
|||||||
@ -48,6 +48,28 @@ object RunescapeRoutines {
|
|||||||
* @param volLogs The number of magic logs to cut into sticks.
|
* @param volLogs The number of magic logs to cut into sticks.
|
||||||
* @param volAshes The number of sticks to coat in ashes.
|
* @param volAshes The number of sticks to coat in ashes.
|
||||||
* @param volCleanHerbs The number of clean herbs to infuse into sticks.
|
* @param volCleanHerbs The number of clean herbs to infuse into sticks.
|
||||||
|
*
|
||||||
|
* This handles the entire incense stick crafting process:
|
||||||
|
* - Cleaning grimy herbs
|
||||||
|
* - Cutting magic logs into sticks
|
||||||
|
* - Coating sticks in ashes
|
||||||
|
* - Infusing clean herbs into sticks
|
||||||
|
*
|
||||||
|
* It loops through each step based on the provided volumes, performing the
|
||||||
|
* actions at the bank.
|
||||||
|
*
|
||||||
|
* Usage example:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* val herbs = 1000
|
||||||
|
* val logs = 2000
|
||||||
|
* val ashes = 1500
|
||||||
|
* val cleanHerbs = herbs + 150
|
||||||
|
*
|
||||||
|
* Routines.fullRunIncense(herbs, logs, ashes, cleanHerbs)
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Progress is printed after each step. Total elapsed time is printed at the end.
|
||||||
*/
|
*/
|
||||||
fun fullRunIncense(volHerbs: Int, volLogs: Int, volAshes: Int, volCleanHerbs: Int) {
|
fun fullRunIncense(volHerbs: Int, volLogs: Int, volAshes: Int, volCleanHerbs: Int) {
|
||||||
val start = System.currentTimeMillis()
|
val start = System.currentTimeMillis()
|
||||||
@ -104,6 +126,24 @@ object RunescapeRoutines {
|
|||||||
* @param agent Optional. The Agent instance to use for banking actions.
|
* @param agent Optional. The Agent instance to use for banking actions.
|
||||||
* @param bankPoint Optional. The Point location of the bank to use.
|
* @param bankPoint Optional. The Point location of the bank to use.
|
||||||
*
|
*
|
||||||
|
* This handles the workflow of:
|
||||||
|
* - Withdrawing grimy herb preset
|
||||||
|
* - Cleaning grimy herbs without dialog
|
||||||
|
* - Depositing clean herbs
|
||||||
|
*
|
||||||
|
* It performs the actions at the bank location using the provided agent.
|
||||||
|
*
|
||||||
|
* Usage examples:
|
||||||
|
* ```
|
||||||
|
* val volume = 1000
|
||||||
|
* val bankPoint = Point(100, 200)
|
||||||
|
* val agent = RSAgent.getInstance()
|
||||||
|
* Routines.cleanHerbs(volume, agent, bankPoint)
|
||||||
|
* ```
|
||||||
|
* Can also omit agent and bankPoint to use defaults:
|
||||||
|
* ```
|
||||||
|
* Routines.cleanHerbs(1000)
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
fun cleanHerbs(volume: Int, agent: RSOrchestrator = RSOrchestrator.getInstance(), bankPoint: Point = agent.getBankPoint()) {
|
fun cleanHerbs(volume: Int, agent: RSOrchestrator = RSOrchestrator.getInstance(), bankPoint: Point = agent.getBankPoint()) {
|
||||||
val params = StandingTaskParams(
|
val params = StandingTaskParams(
|
||||||
@ -126,6 +166,23 @@ object RunescapeRoutines {
|
|||||||
* @param agent Optional. The Agent instance to use for banking actions.
|
* @param agent Optional. The Agent instance to use for banking actions.
|
||||||
* @param bankPoint Optional. The Point location of the bank to use.
|
* @param bankPoint Optional. The Point location of the bank to use.
|
||||||
*
|
*
|
||||||
|
* This handles the workflow of:
|
||||||
|
* - Withdrawing magic log preset
|
||||||
|
* - Cutting magic logs into incense sticks without dialog
|
||||||
|
* - Depositing incense sticks
|
||||||
|
*
|
||||||
|
* Usage examples:
|
||||||
|
* ```
|
||||||
|
* val logs = 1000
|
||||||
|
* val bankPoint = Point(100, 200)
|
||||||
|
* val agent = RSAgent.getInstance()
|
||||||
|
*
|
||||||
|
* Routines.cutIncenseSticks(logs, agent, bankPoint)
|
||||||
|
* ```
|
||||||
|
* Can also omit agent and bankPoint to use defaults:
|
||||||
|
* ```
|
||||||
|
* Routines.cutIncenseSticks(1000)
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
fun cutIncenseSticks(volume: Int, agent: RSOrchestrator = RSOrchestrator.getInstance(), bankPoint: Point = agent.getBankPoint()) {
|
fun cutIncenseSticks(volume: Int, agent: RSOrchestrator = RSOrchestrator.getInstance(), bankPoint: Point = agent.getBankPoint()) {
|
||||||
val params = StandingTaskParams(
|
val params = StandingTaskParams(
|
||||||
@ -148,6 +205,24 @@ object RunescapeRoutines {
|
|||||||
* @param agent Optional Agent instance to use for banking actions.
|
* @param agent Optional Agent instance to use for banking actions.
|
||||||
* @param bankPoint Optional Point location of the bank to use.
|
* @param bankPoint Optional Point location of the bank to use.
|
||||||
*
|
*
|
||||||
|
* This handles the workflow of:
|
||||||
|
* - Withdrawing incense stick preset
|
||||||
|
* - Coating incense sticks with ashes using hotkey
|
||||||
|
* - Depositing coated sticks
|
||||||
|
*
|
||||||
|
* Usage examples:
|
||||||
|
* ```
|
||||||
|
* val sticks = 1000
|
||||||
|
* val bankPoint = Point(100, 200)
|
||||||
|
* val agent = RSAgent.getInstance()
|
||||||
|
*
|
||||||
|
* Routines.coatIncenseSticks(sticks, agent, bankPoint)
|
||||||
|
* ```
|
||||||
|
* Can also omit agent and bankPoint to use defaults:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* Routines.coatIncenseSticks(1000)
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
fun coatIncenseSticks(volume: Int, agent: RSOrchestrator = RSOrchestrator.getInstance(), bankPoint: Point = agent.getBankPoint()) {
|
fun coatIncenseSticks(volume: Int, agent: RSOrchestrator = RSOrchestrator.getInstance(), bankPoint: Point = agent.getBankPoint()) {
|
||||||
val params = StandingTaskParams(
|
val params = StandingTaskParams(
|
||||||
@ -168,6 +243,24 @@ object RunescapeRoutines {
|
|||||||
* @param volume The number of incense sticks to infuse with herbs.
|
* @param volume The number of incense sticks to infuse with herbs.
|
||||||
* @param agent Optional Agent instance to use for banking actions.
|
* @param agent Optional Agent instance to use for banking actions.
|
||||||
* @param bankPoint Optional Point location of the bank to use.
|
* @param bankPoint Optional Point location of the bank to use.
|
||||||
|
*
|
||||||
|
* This handles the workflow of:
|
||||||
|
* - Withdrawing incense stick preset
|
||||||
|
* - Infusing incense sticks with herbs using hotkey
|
||||||
|
* - Depositing infused incense sticks
|
||||||
|
*
|
||||||
|
* Usage examples:
|
||||||
|
* ```
|
||||||
|
* val sticks = 1000
|
||||||
|
* val bankPoint = Point(100, 200)
|
||||||
|
* val agent = RSAgent.getInstance()
|
||||||
|
*
|
||||||
|
* Routines.infuseIncenseSticks(sticks, agent, bankPoint)
|
||||||
|
* ```
|
||||||
|
* Can also omit agent and bankPoint to use defaults:
|
||||||
|
* ```
|
||||||
|
* Routines.infuseIncenseSticks(1000)
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
fun infuseIncenseSticks(volume: Int, agent: RSOrchestrator = RSOrchestrator.getInstance(), bankPoint: Point = agent.getBankPoint()) {
|
fun infuseIncenseSticks(volume: Int, agent: RSOrchestrator = RSOrchestrator.getInstance(), bankPoint: Point = agent.getBankPoint()) {
|
||||||
val params = StandingTaskParams(
|
val params = StandingTaskParams(
|
||||||
@ -189,6 +282,21 @@ object RunescapeRoutines {
|
|||||||
* @param agent The RSOrchestrator instance to use. Defaults to default instance.
|
* @param agent The RSOrchestrator instance to use. Defaults to default instance.
|
||||||
* @param bankPoint The location of the bank. Defaults to agent's configured bank point.
|
* @param bankPoint The location of the bank. Defaults to agent's configured bank point.
|
||||||
*
|
*
|
||||||
|
* This method handles the workflow of crafting potions using hotkeys while standing at a bank:
|
||||||
|
*
|
||||||
|
* - It constructs a StandingTaskParams instance defining:
|
||||||
|
* - The volume, volume per trip, bank point, crafting hotkey, and other details
|
||||||
|
* - It calls the orchestrator's doStandingTask() method to execute the task.
|
||||||
|
*
|
||||||
|
* Usage example:
|
||||||
|
* ```
|
||||||
|
* val volume = 1000
|
||||||
|
* val bankPoint = Point(100, 200)
|
||||||
|
* val agent = RSAgent.getInstance()
|
||||||
|
* Routines.craftPotionsAtBank(volume, agent, bankPoint)
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Progress is automatically printed during execution.
|
||||||
*
|
*
|
||||||
* @deprecated This method needs validation before use in production.
|
* @deprecated This method needs validation before use in production.
|
||||||
*/
|
*/
|
||||||
@ -208,13 +316,32 @@ object RunescapeRoutines {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Grinds potions using a well location for water.
|
* Grinds potions using a well location for water.
|
||||||
* It prompts the user to position the mouse over the well location to get its coordinates.
|
|
||||||
*
|
*
|
||||||
* @param volume The total number of potions to make.
|
* @param volume The total number of potions to make.
|
||||||
* @param travelDurationInMillis The time in ms for the agent to travel between the bank and the well.
|
* @param travelDurationInMillis The time in ms for the agent to travel between the bank and the well.
|
||||||
* @param agent The RSOrchestrator instance to use. Defaults to the default instance.
|
* @param agent The RSOrchestrator instance to use. Defaults to the default instance.
|
||||||
* @param bankPoint The Point location of the bank. Defaults to the agent's configured bank point.
|
* @param bankPoint The Point location of the bank. Defaults to the agent's configured bank point.
|
||||||
*
|
*
|
||||||
|
* This method handles the workflow of grinding potions using a well as the water source.
|
||||||
|
*
|
||||||
|
* It prompts the user to position the mouse over the well location to get its coordinates.
|
||||||
|
*
|
||||||
|
* It then constructs a TravelTaskParams instance to define:
|
||||||
|
* - The volume, volume per trip, bank point, well point, and other task details.
|
||||||
|
*
|
||||||
|
* It calls the orchestrator's doTravelTask() method to execute the grinding task.
|
||||||
|
*
|
||||||
|
* Usage example:
|
||||||
|
* ```
|
||||||
|
* val volume = 1000
|
||||||
|
* val travelDuration = 5000 // 5 seconds
|
||||||
|
* val bankPoint = Point(100, 200)
|
||||||
|
* val wellPoint = Point(300, 400) // Prompted from user
|
||||||
|
* Routines.potionGrindWithWell(volume, travelDuration, bankPoint, wellPoint)
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Progress is automatically printed during execution.
|
||||||
|
*
|
||||||
* @deprecated This method needs validation before use in production.
|
* @deprecated This method needs validation before use in production.
|
||||||
*/
|
*/
|
||||||
@Deprecated("Needs validation before you use it for realsies")
|
@Deprecated("Needs validation before you use it for realsies")
|
||||||
@ -245,14 +372,32 @@ object RunescapeRoutines {
|
|||||||
*
|
*
|
||||||
* @param volume The number of inventory slots to process at the furnace.
|
* @param volume The number of inventory slots to process at the furnace.
|
||||||
*
|
*
|
||||||
* The following 2 values are hard coded from my own personal computer
|
* The following 2 values are hard coded from my own personal setup
|
||||||
* furnaceFromChest The Point location of the furnace from the bank chest.
|
* furnaceFromChest The Point location of the furnace from the bank chest.
|
||||||
* chestFromFurnace The Point location of the bank chest from the furnace.
|
* chestFromFurnace The Point location of the bank chest from the furnace.
|
||||||
|
*
|
||||||
|
* Uses an Agent instance for banking and traveling.
|
||||||
|
*
|
||||||
|
* This handles the workflow of:
|
||||||
|
* - Withdrawing bars at bank chest
|
||||||
|
* - Walking to furnace and processing bars into items
|
||||||
|
* - Walking back to bank and depositing processed items
|
||||||
|
*
|
||||||
|
* The furnace and bank locations are passed in as specific Point locations.
|
||||||
|
* The agent handles the navigation and banking actions.
|
||||||
|
*
|
||||||
|
* Usage example:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* Routines.processAtFurnaceNearBank(1500)
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Before processing, the camera is reset to align points.
|
||||||
*/
|
*/
|
||||||
fun processInventoryAtFurnace(volume: Int) {
|
fun processInventoryAtFurnace(volume: Int) {
|
||||||
//these two points are specific to my computer. we need to export these into a file or something
|
//these two points are specific to my computer. we need to export these into a file or something
|
||||||
val furnaceFromChest = Point(776, 321)
|
val furnaceFromChest = Point(776, 321)
|
||||||
val chestFromFurnance = Point(1813, 893)
|
val chestFromFurnance = Point(1713, 843)
|
||||||
val agent = RSOrchestrator.getInstance()
|
val agent = RSOrchestrator.getInstance()
|
||||||
val params = TravelTaskParams(
|
val params = TravelTaskParams(
|
||||||
volume,
|
volume,
|
||||||
|
|||||||
@ -1,28 +0,0 @@
|
|||||||
package native
|
|
||||||
|
|
||||||
import com.sun.jna.Library
|
|
||||||
import com.sun.jna.Native
|
|
||||||
import com.sun.jna.NativeLong
|
|
||||||
|
|
||||||
|
|
||||||
interface HelloWorldWrapper: Library{
|
|
||||||
companion object {
|
|
||||||
init{
|
|
||||||
System.setProperty(
|
|
||||||
"jna.library.path",
|
|
||||||
"C:\\Users\\Hydros\\IdeaProjects\\RuneFactory\\src\\main\\rust\\src\\build"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getInstance(): HelloWorldWrapper {
|
|
||||||
val options = Native.getLibraryOptions(HelloWorldWrapper::class.java)
|
|
||||||
options[Library.OPTION_FUNCTION_MAPPER] = NativeFunctionMapper()
|
|
||||||
return Native.load("hello", HelloWorldWrapper::class.java, options) as HelloWorldWrapper
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@NativeFunction(name ="_ZN5hello7get_int17h5cc51eaee082b02cE")
|
|
||||||
fun get_int(): NativeLong
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
package native
|
|
||||||
|
|
||||||
import com.sun.jna.NativeLibrary
|
|
||||||
import com.sun.jna.win32.StdCallFunctionMapper
|
|
||||||
import java.lang.reflect.Method
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Annotation used to specify the name of a native function.
|
|
||||||
*
|
|
||||||
* @param name The name of the native function.
|
|
||||||
*/
|
|
||||||
annotation class NativeFunction(val name: String)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mapper class that extends [StdCallFunctionMapper] to using the name from the [NativeFunction] annotation if present
|
|
||||||
* instead of the default name mapping.
|
|
||||||
*
|
|
||||||
* @see StdCallFunctionMapper
|
|
||||||
*/
|
|
||||||
class NativeFunctionMapper : StdCallFunctionMapper() {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overrides the default function name mapping to use the name from the [NativeFunction] annotation if present
|
|
||||||
*
|
|
||||||
* @see StdCallFunctionMapper.getFunctionName
|
|
||||||
*/
|
|
||||||
override fun getFunctionName(library: NativeLibrary?, method: Method): String {
|
|
||||||
return method.getAnnotation(NativeFunction::class.java)?.name ?: super.getFunctionName(library, method)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -32,26 +32,29 @@ object HelperFunctions {
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a random long that approximates a normal distribution.
|
* Generates a random long value approximating a normal distribution.
|
||||||
*
|
*
|
||||||
* Works by taking two random samples from 0 to upperBound/2 and adding them together. This tends to give a more natural
|
* Takes two random samples from 0 to upperBound/2 and adds them together. This approximates a normal distribution
|
||||||
* spread than a single random sample.
|
* better than a single random sample.
|
||||||
*
|
*
|
||||||
* This approach relies on the Central Limit Theorem: that the sum of multiple independent random variables will
|
* @param upperBound The upper bound to sample from
|
||||||
* tend towards a normal distribution, even if the original variables themselves are not normally distributed.
|
* @return A random long value following an approximate normal distribution
|
||||||
*
|
|
||||||
* @param upperBound The upper bound for the random range. Must be >= 2.
|
|
||||||
* @return A random long value following an approximate normal distribution.
|
|
||||||
*/
|
*/
|
||||||
fun getApproximatelyNormalLong(upperBound: Long): Long {
|
fun getGaussianLong(upperBound: Long): Long {
|
||||||
// anything lower to 2 will round down to zero, so return zero. Additionally, this guarantees a positive upper
|
// anything lower to 2 will round down to zero, so return zero. Additionally, this guarantees a positive upper
|
||||||
//bound in one step
|
//bound in one step
|
||||||
if (upperBound < 2L) {
|
if (upperBound <= 2L) {
|
||||||
return 0L
|
return 0L
|
||||||
}
|
}
|
||||||
// Generate two random longs from 0 to upperBound/2 and add them together to approximate a normal distribution.
|
|
||||||
return Random.nextLong(upperBound.shr(1)) + Random.nextLong(upperBound.shr(1))
|
// To create more natural distribution Take two random samples from 0 to upperBound/2 and add them. This
|
||||||
|
// approximates a normal distribution better than single random sample.
|
||||||
|
val subBound = upperBound / 2L
|
||||||
|
val result1 = Random.nextLong(subBound)
|
||||||
|
val result2 = Random.nextLong(subBound)
|
||||||
|
return result1 + result2
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,7 +66,6 @@ object HelperFunctions {
|
|||||||
* @return A random long value
|
* @return A random long value
|
||||||
*/
|
*/
|
||||||
fun getNextGaussian(upperBound: Long): Long {
|
fun getNextGaussian(upperBound: Long): Long {
|
||||||
require(upperBound > 0)
|
|
||||||
return java.util.Random()
|
return java.util.Random()
|
||||||
.nextGaussian(
|
.nextGaussian(
|
||||||
upperBound.toDouble() / 2.0,
|
upperBound.toDouble() / 2.0,
|
||||||
|
|||||||
@ -1,9 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "hello_world"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
|
|
||||||
[build]
|
|
||||||
rustflags = ["-C", "prefer-dynamic"]
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
pub extern fn get_int() -> i32 {
|
|
||||||
return 42;
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
package native
|
|
||||||
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
class DllLoadTest{
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testLoadDll(){
|
|
||||||
val hello = HelloWorldWrapper.getInstance()
|
|
||||||
val i = hello.get_int()
|
|
||||||
assertEquals(i.toInt(), 42)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
@ -2,6 +2,7 @@ package util
|
|||||||
|
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import kotlin.system.measureNanoTime
|
import kotlin.system.measureNanoTime
|
||||||
|
import kotlin.system.measureTimeMillis
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
|
|
||||||
|
|
||||||
@ -15,7 +16,7 @@ class HelperFunctionsTest {
|
|||||||
val numSamples = 10000
|
val numSamples = 10000
|
||||||
val upperBound = 1000L
|
val upperBound = 1000L
|
||||||
val samples = (1..numSamples).map {
|
val samples = (1..numSamples).map {
|
||||||
HelperFunctions.getApproximatelyNormalLong(upperBound)
|
HelperFunctions.getGaussianLong(upperBound)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate mean and standard deviation
|
// Calculate mean and standard deviation
|
||||||
@ -39,7 +40,7 @@ class HelperFunctionsTest {
|
|||||||
val samples = ArrayList<Long>(iterations)
|
val samples = ArrayList<Long>(iterations)
|
||||||
|
|
||||||
val time = doBenchmark(iterations, upperBound) {
|
val time = doBenchmark(iterations, upperBound) {
|
||||||
val v = HelperFunctions.getApproximatelyNormalLong(it)
|
val v = HelperFunctions.getGaussianLong(it)
|
||||||
samples.add(v)
|
samples.add(v)
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
@ -104,7 +105,7 @@ class HelperFunctionsTest {
|
|||||||
println("Warming up for a few iterations")
|
println("Warming up for a few iterations")
|
||||||
val consumer = ArrayList<Long>(iterations)
|
val consumer = ArrayList<Long>(iterations)
|
||||||
repeat(iterations){
|
repeat(iterations){
|
||||||
consumer.add(HelperFunctions.getApproximatelyNormalLong(upperBound))
|
consumer.add(HelperFunctions.getGaussianLong(upperBound))
|
||||||
consumer.add(HelperFunctions.getNextGaussian(upperBound))
|
consumer.add(HelperFunctions.getNextGaussian(upperBound))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +114,7 @@ class HelperFunctionsTest {
|
|||||||
var total = 0L
|
var total = 0L
|
||||||
val time1 = measureNanoTime {
|
val time1 = measureNanoTime {
|
||||||
repeat(iterations) {
|
repeat(iterations) {
|
||||||
total += HelperFunctions.getApproximatelyNormalLong(upperBound)
|
total += HelperFunctions.getGaussianLong(upperBound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user