From d88128c7f9e1b6ff9ce95ba75625734d8ef04a55 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 12 Jan 2024 14:56:03 +0200 Subject: [PATCH 01/26] MISC --- agent-py-bot/API.txt | 75 +++++++++++++++++++++++++ agent-py-bot/agent.py | 5 ++ agent-py-bot/scrape/raw/summary_log.txt | 19 +++++++ 3 files changed, 99 insertions(+) create mode 100644 agent-py-bot/API.txt diff --git a/agent-py-bot/API.txt b/agent-py-bot/API.txt new file mode 100644 index 0000000..9617313 --- /dev/null +++ b/agent-py-bot/API.txt @@ -0,0 +1,75 @@ +https://docs.dexscreener.com/api/reference + +https://api.dexscreener.com/latest/dex/search/?q=:q +https://api.dexscreener.com/latest/dex/pairs/:chainId/:pairAddresses +https://api.dexscreener.com/latest/dex/pairs/bsc/0xcc4Eac613075c14B5252d57C5fBd43ccb1196062 + + + +https://api.dexscreener.com/latest/dex/search/?q=BLACKY/WFTM +https://api.dexscreener.com/latest/dex/pairs/bsc/0xcc4Eac613075c14B5252d57C5fBd43ccb1196062 + + + +https://api.ftmscan.com/api + air: 3UT57M7CYQWDI8YVZC8MN5ERNZ4B783PQV + +https://docs.ftmscan.com/api-endpoints/accounts +Get FTM Balance for a Single Address + https://api.ftmscan.com/api + ?module=account + &action=balance + &address=0x5A534988535cf27a70e74dFfe299D06486f185B7 + &apikey=YourApiKeyToken + + +# Get a list of 'Normal' Transactions By Address +https://api.ftmscan.com/api + ?module=account + &action=txlist + &address=0xb91dd8225Db88dE4E3CD7B7eC538677A2c1Be8Cb + &startblock=0 + &endblock=99999999 + &page=1 + &offset=10 + &sort=asc + &apikey=YourApiKeyToken + +Get a list of 'Internal' Transactions by Address +https://api.ftmscan.com/api + ?module=account + &action=txlistinternal + &address=0xf491e7b69e4244ad4002bc14e878a34207e38c29 + &startblock=0 + &endblock=99999999 + &page=1 + &offset=10 + &sort=asc + &apikey=YourApiKeyToken + + +Get a list of 'ERC-20 Token Transfer Events' by Address +https://api.ftmscan.com/api + ?module=account + &action=tokentx + &contractaddress=0x69c744d3444202d35a2783929a0f930f2fbb05ad + &address=0x489d55df278224a05f793098d41753d5669d5144 + &startblock=0 + &endblock=99999999 + &page=1 + &offset=5 + &sort=asc + &apikey=YourApiKeyToken + +# NFT +https://api.ftmscan.com/api + ?module=account + &action=tokennfttx + &contractaddress=0x428b68C856ACD8e7eae3C5CeB5d650AEaa7F48bc + &address=0xc28bb91d5a8d4d4715cd8666d4e1aa0089b7bee5 + &startblock=0 + &endblock=99999999 + &page=1 + &offset=100 + &sort=asc + &apikey=YourApiKeyToken \ No newline at end of file diff --git a/agent-py-bot/agent.py b/agent-py-bot/agent.py index 746912f..5967b98 100644 --- a/agent-py-bot/agent.py +++ b/agent-py-bot/agent.py @@ -74,6 +74,11 @@ async def ok(update: Update, context: CallbackContext): context.chat_data['messages'] = [] await update.message.reply_text("Exiting ask mode.") +async def brief(update: Update, context: CallbackContext): + + + await update.message.reply_text("Exiting ask mode.") + # CODE RUNNER import re from agents.runner import execute_python_code diff --git a/agent-py-bot/scrape/raw/summary_log.txt b/agent-py-bot/scrape/raw/summary_log.txt index d2f0783..b936fad 100644 --- a/agent-py-bot/scrape/raw/summary_log.txt +++ b/agent-py-bot/scrape/raw/summary_log.txt @@ -27,3 +27,22 @@ The debut of this new technology could potentially revolutionize the EV industry Bragar Eagel & Squire, P.C., a shareholder rights law firm, is reminding investors that class actions have been commenced against Mercury Systems, Inc. (NASDAQ: MRCY) and ON Semiconductor Corporation (NASDAQ: ON). The firm encourages investors to contact them if they suffered losses while holding shares of these companies between specified dates. The lawsuits allege that the companies made false and/or misleading statements and/or failed to disclose important information about their financial condition, business operations, and prospects. Investors who purchased shares of these companies during the class period may be eligible for compensation if it is determined that the companies violated securities laws. However, it is not clear what potential outcome or settlement may result from these lawsuits. + + + +2024-01-08 19:55:08.830427: 1. GM Inches Out Ford In EV Sales In 2023 — Charts: +GM was the leader of the US EV market among legacy automakers for several years.* Going back to the early... [continued]The post GM Inches Out Ford In EV Sales In 2023 — Charts appeared first on CleanTechnica. +2. XING Mobility Debuts Next Generation Immersion Cooling Battery, the Game Changer for Electric Vehicles & Utility Power: +XING Mobility Debuts Next Generation Immersion Cooling Battery, the Game Changer for Electric Vehicles & Utility Power XING Mobility Debuts Next Generation Immersion Cooling Battery, the Game Changer for Electric Vehicles & Utility Po... +3. Bragar Eagel & Squire, P.C. Reminds Investors That Class Action Lawsuits Have Been Filed Against Mercury Systems, and onsemi and Encourages Investors to Contact the Firm: +NEW YORK, Jan. 05, 2024 (GLOBE NEWSWIRE) -- Bragar Eagal & Squire, P.C., a nationally recognized shareholder rights law firm, reminds investors that class actions have been commenced on behalf of stockholders of Mercury Systems, Inc. (NASDAQ: MRCY), and ON Se... +4. For Tesla Stock, A Story About Elon Musk's Drug Use Means ...: +Tesla (TSLA), BYD Will Stay Ahead of Volkswagen (VW) For Years ...Elon Musk's Drug Use Is the Latest Headache for Tesla's BoardTesla FSD beta v12 could see wider release later this monthCould this be our first look at the updated Tesla Model Y? | CarExpe + + + +2024-01-08 21:49:47.465453: The first headline, "Tesla may underpromise and overdeliver with the Model 3 Highland," is from Teslarati. The article reports that Tesla's Model 3 Highland might offer more range than currently advertised, as it is capable of achieving up to 402 miles on a single charge. + +The second headline, "Could this be our first look at the updated Tesla Model Y?," is from CarExpert. The article shares an image that appears to show the refreshed Tesla Model Y, featuring redesigned front and rear bumpers and new lighting elements. However, Tesla has not officially released any images of the updated Model Y. + +The third headline, "For Tesla Stock, A Story About Elon Musk's Drug Use ...", and the fourth headline, "Elon Musk's Drug Use Is the Latest Headache for Tesla's Board," are from The Street. The article discusses how a report about Elon Musk' From 5b700c45ad3cede7e4095186495c0c135a464671 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 12 Jan 2024 15:18:36 +0200 Subject: [PATCH 02/26] niki first --- Niki/tradingview.pinescript | 117 ++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 Niki/tradingview.pinescript diff --git a/Niki/tradingview.pinescript b/Niki/tradingview.pinescript new file mode 100644 index 0000000..47795fa --- /dev/null +++ b/Niki/tradingview.pinescript @@ -0,0 +1,117 @@ +//@version=5 +indicator("drniki nuke", shorttitle="DN", overlay=true) + +// Relative Strength Index (RSI) +rsiLength = input(14, title="RSI Length") +rsiValue = ta.rsi(close, rsiLength) + +// Stochastic RSI +stochRsiLength = input(14, title="Stochastic RSI Length") +stochRsiValue = ta.stoch(close, close, close, stochRsiLength) + +// Wavetrend Indicator +n1 = input(10, "Channel Length") +n2 = input(21, "Average Length") +obLevel1 = input(60, "Over Bought Level 1") +obLevel2 = input(53, "Over Bought Level 2") +osLevel1 = input(-60, "Over Sold Level 1") +osLevel2 = input(-53, "Over Sold Level 2") + +ap = hlc3 +esa = ta.ema(ap, n1) +d = ta.ema(math.abs(ap - esa), n1) +ci = (ap - esa) / (0.015 * d) +tci = ta.ema(ci, n2) + +wt1 = tci +wt2 = ta.sma(wt1, 4) + +// Initialize points for BTCUSDT.P +longPointsRSIBTC = close > close[1] ? 1 : 0 +shortPointsRSIBTC = close < close[1] ? 1 : 0 +longPointsStochRSIBTC = stochRsiValue > stochRsiValue[1] ? 1 : 0 +shortPointsStochRSIBTC = stochRsiValue < stochRsiValue[1] ? 1 : 0 +longPointsWavetrendBTC = wt1 > wt1[1] ? 1 : 0 +shortPointsWavetrendBTC = wt1 < wt1[1] ? 1 : 0 + +// Initialize points for DXY +longPointsRSIDXY = close > close[1] ? 1 : 0 +shortPointsRSIDXY = close < close[1] ? 1 : 0 +longPointsStochRSIDXY = stochRsiValue > stochRsiValue[1] ? 1 : 0 +shortPointsStochRSIDXY = stochRsiValue < stochRsiValue[1] ? 1 : 0 +longPointsWavetrendDXY = wt1 < wt1[1] ? 1 : 0 // Inversed for DXY +shortPointsWavetrendDXY = wt1 > wt1[1] ? 1 : 0 // Inversed for DXY + +// Initialize points for GOLD +longPointsRSIGOLD = close > close[1] ? 1 : 0 +shortPointsRSIGOLD = close < close[1] ? 1 : 0 +longPointsStochRSIGOLD = stochRsiValue > stochRsiValue[1] ? 1 : 0 +shortPointsStochRSIGOLD = stochRsiValue < stochRsiValue[1] ? 1 : 0 +longPointsWavetrendGOLD = wt1 > wt1[1] ? 1 : 0 +shortPointsWavetrendGOLD = wt1 < wt1[1] ? 1 : 0 + +// Initialize points for US30 +longPointsRSIUS30 = close > close[1] ? 1 : 0 +shortPointsRSIUS30 = close < close[1] ? 1 : 0 +longPointsStochRSIUS30 = stochRsiValue > stochRsiValue[1] ? 1 : 0 +shortPointsStochRSIUS30 = stochRsiValue < stochRsiValue[1] ? 1 : 0 +longPointsWavetrendUS30 = wt1 > wt1[1] ? 1 : 0 +shortPointsWavetrendUS30 = wt1 < wt1[1] ? 1 : 0 + +// Initialize points for the current trading pair (PAIR) +longPointsRSIPAIR = close > close[1] ? 1 : 0 +shortPointsRSIPAIR = close < close[1] ? 1 : 0 +longPointsStochRSIPAIR = stochRsiValue > stochRsiValue[1] ? 1 : 0 +shortPointsStochRSIPAIR = stochRsiValue < stochRsiValue[1] ? 1 : 0 +longPointsWavetrendPAIR = wt1 > wt1[1] ? 1 : 0 +shortPointsWavetrendPAIR = wt1 < wt1[1] ? 1 : 0 + +// Adjust the total points calculation for DXY +totalLongPointsDXY = longPointsRSIDXY + longPointsStochRSIDXY + shortPointsWavetrendDXY +totalShortPointsDXY = shortPointsRSIDXY + shortPointsStochRSIDXY + longPointsWavetrendDXY + +// Calculate total points for each symbol +totalLongPointsBTC = longPointsRSIBTC + longPointsStochRSIBTC + longPointsWavetrendBTC +totalShortPointsBTC = shortPointsRSIBTC + shortPointsStochRSIBTC + shortPointsWavetrendBTC + +totalLongPointsGOLD = longPointsRSIGOLD + longPointsStochRSIGOLD + longPointsWavetrendGOLD +totalShortPointsGOLD = shortPointsRSIGOLD + shortPointsStochRSIGOLD + shortPointsWavetrendGOLD + +totalLongPointsUS30 = longPointsRSIUS30 + longPointsStochRSIUS30 + longPointsWavetrendUS30 +totalShortPointsUS30 = shortPointsRSIUS30 + shortPointsStochRSIUS30 + shortPointsWavetrendUS30 + +totalLongPointsPAIR = longPointsRSIPAIR + longPointsStochRSIPAIR + longPointsWavetrendPAIR +totalShortPointsPAIR = shortPointsRSIPAIR + shortPointsStochRSIPAIR + shortPointsWavetrendPAIR + +// Calculate total long and short probabilities for all symbols +totalLongPoints = totalLongPointsBTC + totalLongPointsDXY + totalLongPointsGOLD + totalLongPointsUS30 + totalLongPointsPAIR +totalShortPoints = totalShortPointsBTC + totalShortPointsDXY + totalShortPointsGOLD + totalShortPointsUS30 + totalShortPointsPAIR + +// Calculate combined probabilities for each symbol +combinedProbabilityLongBTC = totalLongPointsBTC / 3 * 100 +combinedProbabilityShortBTC = totalShortPointsBTC / 3 * 100 + +combinedProbabilityLongDXY = totalLongPointsDXY / 3 * 100 +combinedProbabilityShortDXY = totalShortPointsDXY / 3 * 100 + +combinedProbabilityLongGOLD = totalLongPointsGOLD / 3 * 100 +combinedProbabilityShortGOLD = totalShortPointsGOLD / 3 * 100 + +combinedProbabilityLongUS30 = totalLongPointsUS30 / 3 * 100 +combinedProbabilityShortUS30 = totalShortPointsUS30 / 3 * 100 + +combinedProbabilityLongPAIR = totalLongPointsPAIR / 3 * 100 +combinedProbabilityShortPAIR = totalShortPointsPAIR / 3 * 100 + +// Calculate combined probabilities for all symbols +combinedProbabilityLong = totalLongPoints / 15 * 100 +combinedProbabilityShort = totalShortPoints / 15 * 100 + +// Display combined probabilities in a box at the top right corner +var labelBox = label.new(na, na, "") +label.set_xy(labelBox, bar_index, high) + +label.set_text(labelBox, "Long: BTC " + str.tostring(combinedProbabilityLongBTC) + "%, DXY " + str.tostring(combinedProbabilityLongDXY) + "%, GOLD " + str.tostring(combinedProbabilityLongGOLD) + "%, US30 " + str.tostring(combinedProbabilityLongUS30) + "%, PAIR " + str.tostring(combinedProbabilityLongPAIR) + "%\nShort: BTC " + str.tostring(combinedProbabilityShortBTC) + "%, DXY " + str.tostring(combinedProbabilityShortDXY) + "%, GOLD " + str.tostring(combinedProbabilityShortGOLD) + "%, US30 " + str.tostring(combinedProbabilityShortUS30) + "%, PAIR " + str.tostring(combinedProbabilityShortPAIR) + "%\n\nTotal: Long " + str.tostring(combinedProbabilityLong) + "%, Short " + str.tostring(combinedProbabilityShort) + "%") + +label.set_color(labelBox, color.new(color.blue, 0)) +label.set_style(labelBox, label.style_label_left) \ No newline at end of file From dc411abbf5e5b2b808810371841731df406d2122 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 12 Jan 2024 15:24:16 +0200 Subject: [PATCH 03/26] niki's changes --- Niki/tradingview.pinescript | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Niki/tradingview.pinescript b/Niki/tradingview.pinescript index 47795fa..0bb7deb 100644 --- a/Niki/tradingview.pinescript +++ b/Niki/tradingview.pinescript @@ -1,5 +1,5 @@ //@version=5 -indicator("drniki nuke", shorttitle="DN", overlay=true) +indicator("DrNiki's Market Nuker", shorttitle="DrNiki's Market Nuker", overlay=true) // Relative Strength Index (RSI) rsiLength = input(14, title="RSI Length") @@ -58,7 +58,7 @@ shortPointsStochRSIUS30 = stochRsiValue < stochRsiValue[1] ? 1 : 0 longPointsWavetrendUS30 = wt1 > wt1[1] ? 1 : 0 shortPointsWavetrendUS30 = wt1 < wt1[1] ? 1 : 0 -// Initialize points for the current trading pair (PAIR) +// Initialize points for the current trading pair (syminfo.ticker) longPointsRSIPAIR = close > close[1] ? 1 : 0 shortPointsRSIPAIR = close < close[1] ? 1 : 0 longPointsStochRSIPAIR = stochRsiValue > stochRsiValue[1] ? 1 : 0 @@ -110,8 +110,6 @@ combinedProbabilityShort = totalShortPoints / 15 * 100 // Display combined probabilities in a box at the top right corner var labelBox = label.new(na, na, "") label.set_xy(labelBox, bar_index, high) - -label.set_text(labelBox, "Long: BTC " + str.tostring(combinedProbabilityLongBTC) + "%, DXY " + str.tostring(combinedProbabilityLongDXY) + "%, GOLD " + str.tostring(combinedProbabilityLongGOLD) + "%, US30 " + str.tostring(combinedProbabilityLongUS30) + "%, PAIR " + str.tostring(combinedProbabilityLongPAIR) + "%\nShort: BTC " + str.tostring(combinedProbabilityShortBTC) + "%, DXY " + str.tostring(combinedProbabilityShortDXY) + "%, GOLD " + str.tostring(combinedProbabilityShortGOLD) + "%, US30 " + str.tostring(combinedProbabilityShortUS30) + "%, PAIR " + str.tostring(combinedProbabilityShortPAIR) + "%\n\nTotal: Long " + str.tostring(combinedProbabilityLong) + "%, Short " + str.tostring(combinedProbabilityShort) + "%") - +label.set_text(labelBox, "Long: BTC " + str.tostring(combinedProbabilityLongBTC) + "%, DXY " + str.tostring(combinedProbabilityLongDXY) + "%, GOLD " + str.tostring(combinedProbabilityLongGOLD) + "%, US30 " + str.tostring(combinedProbabilityLongUS30) + "%, syminfo.ticker " + str.tostring(combinedProbabilityLongPAIR) + "%\nShort: BTC " + str.tostring(combinedProbabilityShortBTC) + "%, DXY " + str.tostring(combinedProbabilityShortDXY) + "%, GOLD " + str.tostring(combinedProbabilityShortGOLD) + "%, US30 " + str.tostring(combinedProbabilityShortUS30) + "%, syminfo.ticker " + str.tostring(combinedProbabilityShortPAIR) + "%\n\nTotal: Long " + str.tostring(combinedProbabilityLong) + "%, Short " + str.tostring(combinedProbabilityShort) + "%") label.set_color(labelBox, color.new(color.blue, 0)) label.set_style(labelBox, label.style_label_left) \ No newline at end of file From 40968f95add334fa6939028bdf75fb4debde710c Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 12 Jan 2024 15:30:39 +0200 Subject: [PATCH 04/26] new script - scafold --- Niki/new.pinescript | 52 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 Niki/new.pinescript diff --git a/Niki/new.pinescript b/Niki/new.pinescript new file mode 100644 index 0000000..7e7ea4c --- /dev/null +++ b/Niki/new.pinescript @@ -0,0 +1,52 @@ +//@version=4 +study("DrNiki Nuke", shorttitle="DrNiki Nuke", overlay=true) + +// Define pairs and timeframes +string[] pairs = ["US30", "GOLD", "DXY", "BTCUSDT.P", syminfo.ticker] +int[] timeframes = [60, 120, 180, 240] // Timeframes in minutes + +// Initialize variables for odds and points +var float[] longOdds = array.new_float(0) +var float[] shortOdds = array.new_float(0) + + +wavetrendPoints(pair, timeframe) => + wt1 = ... // Your calculation for wavetrend wt1 here + wt1[0] > wt1[1] ? 1 : wt1[0] < wt1[1] ? -1 : 0 + +rsiPoints(pair, timeframe) => + rsiValue = rsi(close, 14) // Example: using 14 periods for RSI + rsiValue[0] > rsiValue[1] ? 1 : rsiValue[0] < rsiValue[1] ? -1 : 0 + +stochRsiKPoints(pair, timeframe) => + K = stoch(close, high, low, 14) // Example: using 14 periods for Stoch RSI + K[0] > K[1] ? 1 : K[0] < K[1] ? -1 : 0 + +obvPoints(pair, timeframe) => + obvValue = obv(close, volume) + obvValue[0] > obvValue[1] ? 1 : obvValue[0] < obvValue[1] ? -1 : 0 + + +// Function to calculate points for indicators +calcPoints(indicator, current, previous) => + + +// Main Calculation Loop +for pair in pairs + for timeframe in timeframes + // Switch to pair and timeframe + ... + // Calculate points for each indicator + longPoints = calcPoints(wt1, ...) + calcPoints(rsi, ...) + ... + shortPoints = calcPoints(wt1, ...) + calcPoints(rsi, ...) + ... + // Inverse for DXY + if pair == "DXY" + ... + // Normalize to get odds + longOdds = ... + shortOdds = ... + // Display results + ... + +// Combine and display most efficient combinations +... From 5af8896e401ba8ee975ffc0ea132b53097b866ed Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 12 Jan 2024 15:38:26 +0200 Subject: [PATCH 05/26] changes --- Niki/new.pinescript | 107 ++++++++++++++++++++++-------------- Niki/tradingview.pinescript | 3 + 2 files changed, 68 insertions(+), 42 deletions(-) diff --git a/Niki/new.pinescript b/Niki/new.pinescript index 7e7ea4c..e6b9576 100644 --- a/Niki/new.pinescript +++ b/Niki/new.pinescript @@ -1,52 +1,75 @@ -//@version=4 -study("DrNiki Nuke", shorttitle="DrNiki Nuke", overlay=true) +//@version=5 +indicator("DrNiki's Market Nuker", shorttitle="DrNiki's Market Nuker", overlay=true) -// Define pairs and timeframes -string[] pairs = ["US30", "GOLD", "DXY", "BTCUSDT.P", syminfo.ticker] -int[] timeframes = [60, 120, 180, 240] // Timeframes in minutes +// Input for Indicators +rsiLength = input(14, title="RSI Length") +stochRsiLength = input(14, title="Stochastic RSI Length") +n1 = input(10, title="WT Channel Length") +n2 = input(21, title="WT Average Length") -// Initialize variables for odds and points -var float[] longOdds = array.new_float(0) -var float[] shortOdds = array.new_float(0) +// Wavetrend Indicator Calculation +ap = hlc3 +esa = ta.ema(ap, n1) +d = ta.ema(math.abs(ap - esa), n1) +ci = (ap - esa) / (0.015 * d) +tci = ta.ema(ci, n2) +wt1 = tci +wt2 = ta.sma(wt1, 4) +// RSI and Stochastic RSI Calculation +rsiValue = ta.rsi(close, rsiLength) +stochRsiValue = ta.stoch(rsiValue, rsiValue, rsiValue, stochRsiLength) -wavetrendPoints(pair, timeframe) => - wt1 = ... // Your calculation for wavetrend wt1 here - wt1[0] > wt1[1] ? 1 : wt1[0] < wt1[1] ? -1 : 0 +// Function to calculate points for a given indicator and pair +calcPoints(currentValue, previousValue, isInverse) => + if isInverse + currentValue < previousValue ? 1 : currentValue > previousValue ? -1 : 0 + else + currentValue > previousValue ? 1 : currentValue < previousValue ? -1 : 0 -rsiPoints(pair, timeframe) => - rsiValue = rsi(close, 14) // Example: using 14 periods for RSI - rsiValue[0] > rsiValue[1] ? 1 : rsiValue[0] < rsiValue[1] ? -1 : 0 +// Calculate points for each currency pair +longPoints(pair, isInverse) => + rsiP = calcPoints(rsiValue, rsiValue[1], isInverse) + stochRsiP = calcPoints(stochRsiValue, stochRsiValue[1], isInverse) + wavetrendP = calcPoints(wt1, wt1[1], isInverse) + rsiP + stochRsiP + wavetrendP -stochRsiKPoints(pair, timeframe) => - K = stoch(close, high, low, 14) // Example: using 14 periods for Stoch RSI - K[0] > K[1] ? 1 : K[0] < K[1] ? -1 : 0 +shortPoints(pair, isInverse) => -longPoints(pair, isInverse) -obvPoints(pair, timeframe) => - obvValue = obv(close, volume) - obvValue[0] > obvValue[1] ? 1 : obvValue[0] < obvValue[1] ? -1 : 0 +// Pairs and their corresponding inverse flag +var pairs = array.new_string(5) +var isInverse = array.new_bool(5) +array.set(pairs, 0, "US30") +array.set(pairs, 1, "GOLD") +array.set(pairs, 2, "DXY") // DXY is inversed +array.set(pairs, 3, "BTCUSDT.P") +array.set(pairs, 4, syminfo.ticker) +array.set(isInverse, 0, false) +array.set(isInverse, 1, false) +array.set(isInverse, 2, true) // Inverse for DXY +array.set(isInverse, 3, false) +array.set(isInverse, 4, false) - -// Function to calculate points for indicators -calcPoints(indicator, current, previous) => - +// Initialize arrays for storing points +var longPointsArray = array.new_float(size = 5, initial_value = 0) +var shortPointsArray = array.new_float(size = 5, initial_value = 0) -// Main Calculation Loop -for pair in pairs - for timeframe in timeframes - // Switch to pair and timeframe - ... - // Calculate points for each indicator - longPoints = calcPoints(wt1, ...) + calcPoints(rsi, ...) + ... - shortPoints = calcPoints(wt1, ...) + calcPoints(rsi, ...) + ... - // Inverse for DXY - if pair == "DXY" - ... - // Normalize to get odds - longOdds = ... - shortOdds = ... - // Display results - ... +// Calculate points for each pair +for i = 0 to array.size(pairs) - 1 + pair = array.get(pairs, i) + inverseFlag = array.get(isInverse, i) + array.set(longPointsArray, i, longPoints(pair, inverseFlag)) + array.set(shortPointsArray, i, shortPoints(pair, inverseFlag)) -// Combine and display most efficient combinations -... +// Calculate total points +totalLongPoints = array.sum(longPointsArray) +totalShortPoints = array.sum(shortPointsArray) + +// Display the results +for i = 0 to array.size(pairs) - 1 + pair = array.get(pairs, i) + plot(array.get(longPointsArray, i), title="Long Points " + pair, color=color.green) + plot(array.get(shortPointsArray, i), title="Short Points " + pair, color=color.red) + +plot(totalLongPoints, title="Total Long Points", color=color.blue) +plot(totalShortPoints, title="Total Short Points", color=color.orange) diff --git a/Niki/tradingview.pinescript b/Niki/tradingview.pinescript index 0bb7deb..9d2be0e 100644 --- a/Niki/tradingview.pinescript +++ b/Niki/tradingview.pinescript @@ -26,6 +26,9 @@ tci = ta.ema(ci, n2) wt1 = tci wt2 = ta.sma(wt1, 4) +//calculate obv +obv = ta.obv(close, volume) + // Initialize points for BTCUSDT.P longPointsRSIBTC = close > close[1] ? 1 : 0 shortPointsRSIBTC = close < close[1] ? 1 : 0 From 4fa8babccc36e9154811b27d6a71dcd6abea4bff Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 12 Jan 2024 15:53:51 +0200 Subject: [PATCH 06/26] misc --- Niki/new.pinescript | 9 ++++++++- Niki/tradingview.pinescript | 5 +++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Niki/new.pinescript b/Niki/new.pinescript index e6b9576..654a8cd 100644 --- a/Niki/new.pinescript +++ b/Niki/new.pinescript @@ -1,4 +1,4 @@ -//@version=5 +//@version=4 indicator("DrNiki's Market Nuker", shorttitle="DrNiki's Market Nuker", overlay=true) // Input for Indicators @@ -73,3 +73,10 @@ for i = 0 to array.size(pairs) - 1 plot(totalLongPoints, title="Total Long Points", color=color.blue) plot(totalShortPoints, title="Total Short Points", color=color.orange) + + +// BUYING VOLUME AND SELLING VOLUME // +buyVolume = iff( (high==low), 0, volume*(close-low)/(high-low)) +sellVolume = iff( (high==low), 0, volume*(high-close)/(high-low)) +plot(volume, style=plot.style_columns, color=color.red, title="SELL V") // shows total volume (!) +plot(buyVolume, style=plot.style_columns, color=color.teal, title="BUY V") // shows only buy volume diff --git a/Niki/tradingview.pinescript b/Niki/tradingview.pinescript index 9d2be0e..b9e592c 100644 --- a/Niki/tradingview.pinescript +++ b/Niki/tradingview.pinescript @@ -28,6 +28,11 @@ wt2 = ta.sma(wt1, 4) //calculate obv obv = ta.obv(close, volume) +//15:38:24 Error at 30:7 Could not find function or function reference 'ta.obv' + +//calculate mfi +mfi = ta.mfi(high, low, close, volume) + // Initialize points for BTCUSDT.P longPointsRSIBTC = close > close[1] ? 1 : 0 From 897556f8e44f5d52cfa0e4e58015b1fa7d0df180 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 12 Jan 2024 15:54:25 +0200 Subject: [PATCH 07/26] renames --- Niki/{new.pinescript => new.pine} | 0 Niki/{tradingview.pinescript => niki.pine} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename Niki/{new.pinescript => new.pine} (100%) rename Niki/{tradingview.pinescript => niki.pine} (100%) diff --git a/Niki/new.pinescript b/Niki/new.pine similarity index 100% rename from Niki/new.pinescript rename to Niki/new.pine diff --git a/Niki/tradingview.pinescript b/Niki/niki.pine similarity index 100% rename from Niki/tradingview.pinescript rename to Niki/niki.pine From fca4c10820980ae977ddad4726a5512764a06624 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 12 Jan 2024 15:55:00 +0200 Subject: [PATCH 08/26] new to v4 --- Niki/new.pine | 64 ++++++++++++++++++--------------------------------- 1 file changed, 23 insertions(+), 41 deletions(-) diff --git a/Niki/new.pine b/Niki/new.pine index 654a8cd..3d8392b 100644 --- a/Niki/new.pine +++ b/Niki/new.pine @@ -9,23 +9,25 @@ n2 = input(21, title="WT Average Length") // Wavetrend Indicator Calculation ap = hlc3 -esa = ta.ema(ap, n1) -d = ta.ema(math.abs(ap - esa), n1) +esa = ema(ap, n1) +d = ema(abs(ap - esa), n1) ci = (ap - esa) / (0.015 * d) -tci = ta.ema(ci, n2) +tci = ema(ci, n2) wt1 = tci -wt2 = ta.sma(wt1, 4) +wt2 = sma(wt1, 4) // RSI and Stochastic RSI Calculation -rsiValue = ta.rsi(close, rsiLength) -stochRsiValue = ta.stoch(rsiValue, rsiValue, rsiValue, stochRsiLength) +rsiValue = rsi(close, rsiLength) +stochRsiValue = stoch(rsiValue, rsiValue, rsiValue, stochRsiLength) // Function to calculate points for a given indicator and pair calcPoints(currentValue, previousValue, isInverse) => + value = 0 if isInverse - currentValue < previousValue ? 1 : currentValue > previousValue ? -1 : 0 + value := currentValue < previousValue ? 1 : currentValue > previousValue ? -1 : 0 else - currentValue > previousValue ? 1 : currentValue < previousValue ? -1 : 0 + value := currentValue > previousValue ? 1 : currentValue < previousValue ? -1 : 0 + value // Calculate points for each currency pair longPoints(pair, isInverse) => @@ -36,47 +38,27 @@ longPoints(pair, isInverse) => shortPoints(pair, isInverse) => -longPoints(pair, isInverse) -// Pairs and their corresponding inverse flag -var pairs = array.new_string(5) -var isInverse = array.new_bool(5) -array.set(pairs, 0, "US30") -array.set(pairs, 1, "GOLD") -array.set(pairs, 2, "DXY") // DXY is inversed -array.set(pairs, 3, "BTCUSDT.P") -array.set(pairs, 4, syminfo.ticker) -array.set(isInverse, 0, false) -array.set(isInverse, 1, false) -array.set(isInverse, 2, true) // Inverse for DXY -array.set(isInverse, 3, false) -array.set(isInverse, 4, false) +// Hardcode the pairs and their corresponding inverse flags +pairs = ["US30", "GOLD", "DXY", "BTCUSDT.P", syminfo.tickerid] +isInverse = [false, false, true, false, false] // Inverse for DXY -// Initialize arrays for storing points -var longPointsArray = array.new_float(size = 5, initial_value = 0) -var shortPointsArray = array.new_float(size = 5, initial_value = 0) +// Initialize variables for storing points +var float totalLongPoints = 0 +var float totalShortPoints = 0 // Calculate points for each pair -for i = 0 to array.size(pairs) - 1 - pair = array.get(pairs, i) - inverseFlag = array.get(isInverse, i) - array.set(longPointsArray, i, longPoints(pair, inverseFlag)) - array.set(shortPointsArray, i, shortPoints(pair, inverseFlag)) - -// Calculate total points -totalLongPoints = array.sum(longPointsArray) -totalShortPoints = array.sum(shortPointsArray) +for i = 0 to 4 + pair = pairs[i] + inverseFlag = isInverse[i] + totalLongPoints := totalLongPoints + longPoints(pair, inverseFlag) + totalShortPoints := totalShortPoints + shortPoints(pair, inverseFlag) // Display the results -for i = 0 to array.size(pairs) - 1 - pair = array.get(pairs, i) - plot(array.get(longPointsArray, i), title="Long Points " + pair, color=color.green) - plot(array.get(shortPointsArray, i), title="Short Points " + pair, color=color.red) - plot(totalLongPoints, title="Total Long Points", color=color.blue) plot(totalShortPoints, title="Total Short Points", color=color.orange) - // BUYING VOLUME AND SELLING VOLUME // -buyVolume = iff( (high==low), 0, volume*(close-low)/(high-low)) -sellVolume = iff( (high==low), 0, volume*(high-close)/(high-low)) +buyVolume = high == low ? 0 : volume * (close - low) / (high - low) +sellVolume = high == low ? 0 : volume * (high - close) / (high - low) plot(volume, style=plot.style_columns, color=color.red, title="SELL V") // shows total volume (!) plot(buyVolume, style=plot.style_columns, color=color.teal, title="BUY V") // shows only buy volume From 7e4b76fbec171b633644b5db60762901adf91e26 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 12 Jan 2024 16:09:56 +0200 Subject: [PATCH 09/26] fix array --- Niki/new.pine | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/Niki/new.pine b/Niki/new.pine index 3d8392b..fca83a6 100644 --- a/Niki/new.pine +++ b/Niki/new.pine @@ -38,9 +38,16 @@ longPoints(pair, isInverse) => shortPoints(pair, isInverse) => -longPoints(pair, isInverse) -// Hardcode the pairs and their corresponding inverse flags -pairs = ["US30", "GOLD", "DXY", "BTCUSDT.P", syminfo.tickerid] -isInverse = [false, false, true, false, false] // Inverse for DXY +// Hardcoded pairs and their corresponding inverse flags +pairs = array.new_string(5) +array.set(pairs, 0, "US30") +array.set(pairs, 1, "GOLD") +array.set(pairs, 2, "DXY") +array.set(pairs, 3, "BTCUSDT.P") +array.set(pairs, 4, syminfo.tickerid) + +isInverse = array.new_bool(5, false) +array.set(isInverse, 2, true) // Inverse for DXY // Initialize variables for storing points var float totalLongPoints = 0 @@ -48,8 +55,8 @@ var float totalShortPoints = 0 // Calculate points for each pair for i = 0 to 4 - pair = pairs[i] - inverseFlag = isInverse[i] + pair = array.get(pairs, i) + inverseFlag = array.get(isInverse, i) totalLongPoints := totalLongPoints + longPoints(pair, inverseFlag) totalShortPoints := totalShortPoints + shortPoints(pair, inverseFlag) @@ -57,8 +64,8 @@ for i = 0 to 4 plot(totalLongPoints, title="Total Long Points", color=color.blue) plot(totalShortPoints, title="Total Short Points", color=color.orange) -// BUYING VOLUME AND SELLING VOLUME // +// BUYING VOLUME AND SELLING VOLUME buyVolume = high == low ? 0 : volume * (close - low) / (high - low) sellVolume = high == low ? 0 : volume * (high - close) / (high - low) -plot(volume, style=plot.style_columns, color=color.red, title="SELL V") // shows total volume (!) +plot(volume, style=plot.style_columns, color=color.red, title="SELL V") // shows total volume plot(buyVolume, style=plot.style_columns, color=color.teal, title="BUY V") // shows only buy volume From bae87ad38033295a65a41f635b72907412fd81f4 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 12 Jan 2024 16:14:51 +0200 Subject: [PATCH 10/26] fix errors --- Niki/new.pine | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Niki/new.pine b/Niki/new.pine index fca83a6..386530f 100644 --- a/Niki/new.pine +++ b/Niki/new.pine @@ -1,5 +1,5 @@ //@version=4 -indicator("DrNiki's Market Nuker", shorttitle="DrNiki's Market Nuker", overlay=true) +study("DrNiki's Market Nuker", shorttitle="DrNiki's Market Nuker", overlay=true) // Input for Indicators rsiLength = input(14, title="RSI Length") From 5ef4bad84c367fb68df0ac0c38982bc4253fe37a Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 12 Jan 2024 16:56:05 +0200 Subject: [PATCH 11/26] fix pines --- Niki/new.pine | 50 ++++++++++++++++++++++++++++++--------------- Niki/niki.pine | 55 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 72 insertions(+), 33 deletions(-) diff --git a/Niki/new.pine b/Niki/new.pine index 386530f..626033b 100644 --- a/Niki/new.pine +++ b/Niki/new.pine @@ -1,7 +1,7 @@ -//@version=4 -study("DrNiki's Market Nuker", shorttitle="DrNiki's Market Nuker", overlay=true) +//@version=5 +indicator("DrNiki's Market Nuker", shorttitle="DrNiki's Market Nuker", overlay=true) -// Input for Indicators +// [Input for Indicators] rsiLength = input(14, title="RSI Length") stochRsiLength = input(14, title="Stochastic RSI Length") n1 = input(10, title="WT Channel Length") @@ -9,16 +9,29 @@ n2 = input(21, title="WT Average Length") // Wavetrend Indicator Calculation ap = hlc3 -esa = ema(ap, n1) -d = ema(abs(ap - esa), n1) +esa = ta.ema(ap, n1) +d = ta.ema(math.abs(ap - esa), n1) ci = (ap - esa) / (0.015 * d) -tci = ema(ci, n2) +tci = ta.ema(ci, n2) + wt1 = tci -wt2 = sma(wt1, 4) +wt2 = ta.sma(wt1, 4) + +// Custom implementation of On Balance Volume (OBV) +var float obv = na +obv := close > close[1] ? obv + volume : close < close[1] ? obv - volume : obv + +// Money Flow Index (MFI) +mfiLength = input(7, title="MFI Length") +mfiValue = ta.mfi(close, mfiLength) + // RSI and Stochastic RSI Calculation -rsiValue = rsi(close, rsiLength) -stochRsiValue = stoch(rsiValue, rsiValue, rsiValue, stochRsiLength) +rsiValue = ta.rsi(close, rsiLength) +stochRsiValue = ta.stoch(rsiValue, rsiValue, rsiValue, stochRsiLength) + + +// [Function to calculate points for a given indicator and pair] // Function to calculate points for a given indicator and pair calcPoints(currentValue, previousValue, isInverse) => @@ -38,6 +51,7 @@ longPoints(pair, isInverse) => shortPoints(pair, isInverse) => -longPoints(pair, isInverse) + // Hardcoded pairs and their corresponding inverse flags pairs = array.new_string(5) array.set(pairs, 0, "US30") @@ -54,18 +68,22 @@ var float totalLongPoints = 0 var float totalShortPoints = 0 // Calculate points for each pair +longPointsArray = array.new_float(5) +shortPointsArray = array.new_float(5) for i = 0 to 4 pair = array.get(pairs, i) inverseFlag = array.get(isInverse, i) - totalLongPoints := totalLongPoints + longPoints(pair, inverseFlag) - totalShortPoints := totalShortPoints + shortPoints(pair, inverseFlag) + array.set(longPointsArray, i, longPoints(pair, inverseFlag)) + array.set(shortPointsArray, i, shortPoints(pair, inverseFlag)) + +// Update total points +for i = 0 to 4 + totalLongPoints := totalLongPoints + array.get(longPointsArray, i) + totalShortPoints := totalShortPoints + array.get(shortPointsArray, i) // Display the results plot(totalLongPoints, title="Total Long Points", color=color.blue) plot(totalShortPoints, title="Total Short Points", color=color.orange) -// BUYING VOLUME AND SELLING VOLUME -buyVolume = high == low ? 0 : volume * (close - low) / (high - low) -sellVolume = high == low ? 0 : volume * (high - close) / (high - low) -plot(volume, style=plot.style_columns, color=color.red, title="SELL V") // shows total volume -plot(buyVolume, style=plot.style_columns, color=color.teal, title="BUY V") // shows only buy volume + +// Display \ No newline at end of file diff --git a/Niki/niki.pine b/Niki/niki.pine index b9e592c..e2fd262 100644 --- a/Niki/niki.pine +++ b/Niki/niki.pine @@ -26,13 +26,13 @@ tci = ta.ema(ci, n2) wt1 = tci wt2 = ta.sma(wt1, 4) -//calculate obv -obv = ta.obv(close, volume) -//15:38:24 Error at 30:7 Could not find function or function reference 'ta.obv' - -//calculate mfi -mfi = ta.mfi(high, low, close, volume) +// Custom implementation of On Balance Volume (OBV) +var float obv = na +obv := close > close[1] ? obv + volume : close < close[1] ? obv - volume : obv +// Money Flow Index (MFI) +mfiLength = input(7, title="MFI Length") +mfiValue = ta.mfi(close, mfiLength) // Initialize points for BTCUSDT.P longPointsRSIBTC = close > close[1] ? 1 : 0 @@ -41,14 +41,22 @@ longPointsStochRSIBTC = stochRsiValue > stochRsiValue[1] ? 1 : 0 shortPointsStochRSIBTC = stochRsiValue < stochRsiValue[1] ? 1 : 0 longPointsWavetrendBTC = wt1 > wt1[1] ? 1 : 0 shortPointsWavetrendBTC = wt1 < wt1[1] ? 1 : 0 +longPointsOBVBTC = obv > obv[1] ? 1 : 0 +shortPointsOBVBTC = obv < obv[1] ? 1 : 0 +longPointsMFIBTC = mfiValue > 50 ? 1 : 0 +shortPointsMFIBTC = mfiValue < 50 ? 1 : 0 // Initialize points for DXY -longPointsRSIDXY = close > close[1] ? 1 : 0 -shortPointsRSIDXY = close < close[1] ? 1 : 0 -longPointsStochRSIDXY = stochRsiValue > stochRsiValue[1] ? 1 : 0 -shortPointsStochRSIDXY = stochRsiValue < stochRsiValue[1] ? 1 : 0 -longPointsWavetrendDXY = wt1 < wt1[1] ? 1 : 0 // Inversed for DXY -shortPointsWavetrendDXY = wt1 > wt1[1] ? 1 : 0 // Inversed for DXY +longPointsRSIDXY = close > close[1] ? 0 : 1 +shortPointsRSIDXY = close < close[1] ? 0 : 1 +longPointsStochRSIDXY = stochRsiValue > stochRsiValue[1] ? 0 : 1 +shortPointsStochRSIDXY = stochRsiValue < stochRsiValue[1] ? 0 : 1 +longPointsWavetrendDXY = wt1 < wt1[1] ? 0 : 1 +shortPointsWavetrendDXY = wt1 > wt1[1] ? 0 : 1 +longPointsOBVDXY = obv > obv[1] ? 0 : 1 +shortPointsOBVDXY = obv < obv[1] ? 0 : 1 +longPointsMFIDXY = mfiValue > 50 ? 0 : 1 +shortPointsMFIDXY = mfiValue < 50 ? 0 : 1 // Initialize points for GOLD longPointsRSIGOLD = close > close[1] ? 1 : 0 @@ -57,6 +65,11 @@ longPointsStochRSIGOLD = stochRsiValue > stochRsiValue[1] ? 1 : 0 shortPointsStochRSIGOLD = stochRsiValue < stochRsiValue[1] ? 1 : 0 longPointsWavetrendGOLD = wt1 > wt1[1] ? 1 : 0 shortPointsWavetrendGOLD = wt1 < wt1[1] ? 1 : 0 +longPointsOBVGOLD = obv > obv[1] ? 1 : 0 +shortPointsOBVGOLD = obv < obv[1] ? 1 : 0 +longPointsMFIGOLD = mfiValue > 50 ? 1 : 0 +shortPointsMFIGOLD = mfiValue < 50 ? 1 : 0 + // Initialize points for US30 longPointsRSIUS30 = close > close[1] ? 1 : 0 @@ -65,6 +78,10 @@ longPointsStochRSIUS30 = stochRsiValue > stochRsiValue[1] ? 1 : 0 shortPointsStochRSIUS30 = stochRsiValue < stochRsiValue[1] ? 1 : 0 longPointsWavetrendUS30 = wt1 > wt1[1] ? 1 : 0 shortPointsWavetrendUS30 = wt1 < wt1[1] ? 1 : 0 +longPointsOBVUS30 = obv > obv[1] ? 1 : 0 +shortPointsOBVUS30 = obv < obv[1] ? 1 : 0 +longPointsMFIUS30 = mfiValue > 50 ? 1 : 0 +shortPointsMFIUS30 = mfiValue < 50 ? 1 : 0 // Initialize points for the current trading pair (syminfo.ticker) longPointsRSIPAIR = close > close[1] ? 1 : 0 @@ -73,10 +90,10 @@ longPointsStochRSIPAIR = stochRsiValue > stochRsiValue[1] ? 1 : 0 shortPointsStochRSIPAIR = stochRsiValue < stochRsiValue[1] ? 1 : 0 longPointsWavetrendPAIR = wt1 > wt1[1] ? 1 : 0 shortPointsWavetrendPAIR = wt1 < wt1[1] ? 1 : 0 - -// Adjust the total points calculation for DXY -totalLongPointsDXY = longPointsRSIDXY + longPointsStochRSIDXY + shortPointsWavetrendDXY -totalShortPointsDXY = shortPointsRSIDXY + shortPointsStochRSIDXY + longPointsWavetrendDXY +longPointsOBVPAIR = obv > obv[1] ? 1 : 0 +shortPointsOBVPAIR = obv < obv[1] ? 1 : 0 +longPointsMFIPAIR = mfiValue > 50 ? 1 : 0 +shortPointsMFIPAIR = mfiValue < 50 ? 1 : 0 // Calculate total points for each symbol totalLongPointsBTC = longPointsRSIBTC + longPointsStochRSIBTC + longPointsWavetrendBTC @@ -85,6 +102,9 @@ totalShortPointsBTC = shortPointsRSIBTC + shortPointsStochRSIBTC + shortPointsWa totalLongPointsGOLD = longPointsRSIGOLD + longPointsStochRSIGOLD + longPointsWavetrendGOLD totalShortPointsGOLD = shortPointsRSIGOLD + shortPointsStochRSIGOLD + shortPointsWavetrendGOLD +totalLongPointsDXY = longPointsRSIDXY + longPointsStochRSIDXY + longPointsWavetrendDXY +totalShortPointsDXY = shortPointsRSIDXY + shortPointsStochRSIDXY + shortPointsWavetrendDXY + totalLongPointsUS30 = longPointsRSIUS30 + longPointsStochRSIUS30 + longPointsWavetrendUS30 totalShortPointsUS30 = shortPointsRSIUS30 + shortPointsStochRSIUS30 + shortPointsWavetrendUS30 @@ -120,4 +140,5 @@ var labelBox = label.new(na, na, "") label.set_xy(labelBox, bar_index, high) label.set_text(labelBox, "Long: BTC " + str.tostring(combinedProbabilityLongBTC) + "%, DXY " + str.tostring(combinedProbabilityLongDXY) + "%, GOLD " + str.tostring(combinedProbabilityLongGOLD) + "%, US30 " + str.tostring(combinedProbabilityLongUS30) + "%, syminfo.ticker " + str.tostring(combinedProbabilityLongPAIR) + "%\nShort: BTC " + str.tostring(combinedProbabilityShortBTC) + "%, DXY " + str.tostring(combinedProbabilityShortDXY) + "%, GOLD " + str.tostring(combinedProbabilityShortGOLD) + "%, US30 " + str.tostring(combinedProbabilityShortUS30) + "%, syminfo.ticker " + str.tostring(combinedProbabilityShortPAIR) + "%\n\nTotal: Long " + str.tostring(combinedProbabilityLong) + "%, Short " + str.tostring(combinedProbabilityShort) + "%") label.set_color(labelBox, color.new(color.blue, 0)) -label.set_style(labelBox, label.style_label_left) \ No newline at end of file +label.set_style(labelBox, label.style_label_left) + From 5afee8e343cd5fec1365aa5493321c9dd888ddb7 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 12 Jan 2024 17:17:40 +0200 Subject: [PATCH 12/26] add niki refactored --- Niki/niki-refactored.pine | 85 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 Niki/niki-refactored.pine diff --git a/Niki/niki-refactored.pine b/Niki/niki-refactored.pine new file mode 100644 index 0000000..bcd5d10 --- /dev/null +++ b/Niki/niki-refactored.pine @@ -0,0 +1,85 @@ +//@version=5 +indicator("DrNiki's Market Nuker", shorttitle="DrNiki's Market Nuker", overlay=true) + +// Function to calculate RSI +rsiLength = input(14, title="RSI Length") +calcRSI() => ta.rsi(close, rsiLength) + +// Function to calculate Stochastic RSI +stochRsiLength = input(14, title="Stochastic RSI Length") +calcStochRSI() => ta.stoch(close, close, close, stochRsiLength) + +// Function to calculate Wavetrend +n1 = input(10, "Channel Length") +n2 = input(21, "Average Length") +calcWavetrend() => + ap = hlc3 + esa = ta.ema(ap, n1) + d = ta.ema(math.abs(ap - esa), n1) + ci = (ap - esa) / (0.015 * d) + tci = ta.ema(ci, n2) + wt1 = tci + wt2 = ta.sma(wt1, 4) + [wt1, wt2] + +// Function to calculate On Balance Volume (OBV) +calcOBV() => + var float obv = na + obv := close > close[1] ? obv + volume : close < close[1] ? obv - volume : obv + obv + +// Function to calculate MFI +mfiLength = input(7, title="MFI Length") +calcMFI() => ta.mfi(close, mfiLength) + +// Function to calculate points for a symbol +calcPoints(symbol) => + rsiValue = calcRSI() + stochRsiValue = calcStochRSI() + [wt1, wt2] = calcWavetrend() + obv = calcOBV() + mfiValue = calcMFI() + + longPoints = 0 + shortPoints = 0 + longPoints := rsiValue > rsiValue[1] ? longPoints + 1 : longPoints + shortPoints := rsiValue < rsiValue[1] ? shortPoints + 1 : shortPoints + longPoints := stochRsiValue > stochRsiValue[1] ? longPoints + 1 : longPoints + shortPoints := stochRsiValue < stochRsiValue[1] ? shortPoints + 1 : shortPoints + longPoints := wt1 > wt1[1] ? longPoints + 1 : longPoints + shortPoints := wt1 < wt1[1] ? shortPoints + 1 : shortPoints + longPoints := obv > obv[1] ? longPoints + 1 : longPoints + shortPoints := obv < obv[1] ? shortPoints + 1 : shortPoints + longPoints := mfiValue > 50 ? longPoints + 1 : longPoints + shortPoints := mfiValue < 50 ? shortPoints + 1 : shortPoints + [longPoints, shortPoints] + +// Symbols array +symbols = array.new_string(5) +array.set(symbols, 0, "US30") +array.set(symbols, 1, "GOLD") +array.set(symbols, 2, "DXY") +array.set(symbols, 3, "BTCUSDT.P") +array.set(symbols, 4, syminfo.tickerid) + +// Calculate points for each symbol +var symbolPoints = array.new_int(2, 0) +for symbol in symbols + [longPoints, shortPoints] = calcPoints(symbol) + var logMessage = "Symbol: " + symbol + ", Long: " + str.tostring(longPoints) + ", Short: " + str.tostring(shortPoints) + log.info(logMessage) + array.set(symbolPoints, 0, array.get(symbolPoints, 0) + longPoints) + array.set(symbolPoints, 1, array.get(symbolPoints, 1) + shortPoints) + +// Calculate total long and short probabilities +totalLongPoints = array.get(symbolPoints, 0) +totalShortPoints = array.get(symbolPoints, 1) +combinedProbabilityLong = totalLongPoints / (array.size(symbols) * 3) * 100 +combinedProbabilityShort = totalShortPoints / (array.size(symbols) * 3) * 100 + +// Display combined probabilities +var labelBox = label.new(na, na, "") +label.set_xy(labelBox, bar_index, high) +label.set_text(labelBox, "Combined Probabilities\nLong: " + str.tostring(combinedProbabilityLong) + "%\nShort: " + str.tostring(combinedProbabilityShort) + "%") +label.set_color(labelBox, color.new(color.blue, 0)) +label.set_style(labelBox, label.style_label_left) From 39e2dba692d71c8987ba98278f7174c442e34e6d Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 12 Jan 2024 17:39:10 +0200 Subject: [PATCH 13/26] all compiling --- Niki/new.pine | 36 ++++++++++++++++++++++++++++++++++++ Niki/niki-refactored.pine | 7 +++++-- Niki/niki.pine | 5 +++++ 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/Niki/new.pine b/Niki/new.pine index 626033b..5c04adc 100644 --- a/Niki/new.pine +++ b/Niki/new.pine @@ -1,6 +1,42 @@ //@version=5 indicator("DrNiki's Market Nuker", shorttitle="DrNiki's Market Nuker", overlay=true) + + +// /* +// create a calculator in pinescript that uses all of this data at the same time: +// here are the pairs: +// -US30 +// -GOLD +// -DXY (for this pair inverse the results, each long point goes to a short point and vice versa) +// -BTCUSDT.P +// -syminfo.ticker +// (e.g.:pairs = ["US30", "GOLD", "DXY", "BTCUSDT.P", syminfo.ticker]) + +// use these 4 timeframes: +// 1 hour +// 2 hour +// 3 hour +// 4 hour + +// Use these 4 indicators: + +// Wavetrend with crosses [LazyBear] and use wt1 only - when it goes higher than the previous candle from the timeframe specified (we specified 4 timeframes) give it 1 point for longs. When it goes lower than the previous candle from the current timeframe specified (we specified 4 timeframes) give it 1 point for shorts + +// for rsi do the same + +// for stoch rsi K line do the same + +// for OBV do the same + +// DO it on all pairs and on all timeframes at the same time, the maximum odds should be 100% total. write the results in a text with the odds per pair for a long and short based on each timeframe and pair and based on each pair and timeframe. +// Then have a total when you have the most efficient way of combining them calculated + + +// */ + + + // [Input for Indicators] rsiLength = input(14, title="RSI Length") stochRsiLength = input(14, title="Stochastic RSI Length") diff --git a/Niki/niki-refactored.pine b/Niki/niki-refactored.pine index bcd5d10..0d12665 100644 --- a/Niki/niki-refactored.pine +++ b/Niki/niki-refactored.pine @@ -52,19 +52,22 @@ calcPoints(symbol) => shortPoints := obv < obv[1] ? shortPoints + 1 : shortPoints longPoints := mfiValue > 50 ? longPoints + 1 : longPoints shortPoints := mfiValue < 50 ? shortPoints + 1 : shortPoints + var logMessage = "Symbol: " + symbol + ", Long: " + str.tostring(longPoints) + ", Short: " + str.tostring(shortPoints) + log.info(logMessage) [longPoints, shortPoints] // Symbols array symbols = array.new_string(5) -array.set(symbols, 0, "US30") +array.set(symbols, 0, syminfo.tickerid) array.set(symbols, 1, "GOLD") array.set(symbols, 2, "DXY") array.set(symbols, 3, "BTCUSDT.P") -array.set(symbols, 4, syminfo.tickerid) +array.set(symbols, 4, "US30" ) // Calculate points for each symbol var symbolPoints = array.new_int(2, 0) for symbol in symbols + // Change symbol context using security() function [longPoints, shortPoints] = calcPoints(symbol) var logMessage = "Symbol: " + symbol + ", Long: " + str.tostring(longPoints) + ", Short: " + str.tostring(shortPoints) log.info(logMessage) diff --git a/Niki/niki.pine b/Niki/niki.pine index e2fd262..b8488a7 100644 --- a/Niki/niki.pine +++ b/Niki/niki.pine @@ -34,6 +34,11 @@ obv := close > close[1] ? obv + volume : close < close[1] ? obv - volume : obv mfiLength = input(7, title="MFI Length") mfiValue = ta.mfi(close, mfiLength) + +timeStr = str.tostring(time(timeframe.period, "YYYY-MM-DD HH:mm:ss")) +closeStr = str.tostring(close) +log.info("time: " + timeStr + " close: " + closeStr) + // Initialize points for BTCUSDT.P longPointsRSIBTC = close > close[1] ? 1 : 0 shortPointsRSIBTC = close < close[1] ? 1 : 0 From 1bfb5670b8ec18fa032b055a8269d31d3682e242 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 12 Jan 2024 18:00:43 +0200 Subject: [PATCH 14/26] comments & logs --- Niki/niki-refactored.pine | 5 +++-- Niki/niki.pine | 7 +++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Niki/niki-refactored.pine b/Niki/niki-refactored.pine index 0d12665..aa88fc5 100644 --- a/Niki/niki-refactored.pine +++ b/Niki/niki-refactored.pine @@ -65,11 +65,12 @@ array.set(symbols, 3, "BTCUSDT.P") array.set(symbols, 4, "US30" ) // Calculate points for each symbol -var symbolPoints = array.new_int(2, 0) +var symbolPoints = array.new_int(size=array.size(symbols) * 2, initial_value=0) for symbol in symbols // Change symbol context using security() function [longPoints, shortPoints] = calcPoints(symbol) - var logMessage = "Symbol: " + symbol + ", Long: " + str.tostring(longPoints) + ", Short: " + str.tostring(shortPoints) + barTimeStr = str.format_time(time, "yyyy-MM-dd HH:mm:ss", "Europe/Sofia") + var logMessage = barTimeStr + "| Symbol: " + symbol + ", Long: " + str.tostring(longPoints) + ", Short: " + str.tostring(shortPoints) log.info(logMessage) array.set(symbolPoints, 0, array.get(symbolPoints, 0) + longPoints) array.set(symbolPoints, 1, array.get(symbolPoints, 1) + shortPoints) diff --git a/Niki/niki.pine b/Niki/niki.pine index b8488a7..28c00b4 100644 --- a/Niki/niki.pine +++ b/Niki/niki.pine @@ -35,9 +35,12 @@ mfiLength = input(7, title="MFI Length") mfiValue = ta.mfi(close, mfiLength) -timeStr = str.tostring(time(timeframe.period, "YYYY-MM-DD HH:mm:ss")) +var logMessage = barTimeStr + "| Symbol: " + symbol + ", Long: " + str.tostring(longPoints) + ", Short: " + str.tostring(shortPoints) +log.info(logMessage) + +barTimeStr = str.format_time(time, "yyyy-MM-dd HH:mm:ss", "Europe/Sofia") closeStr = str.tostring(close) -log.info("time: " + timeStr + " close: " + closeStr) +log.info(barTimeStr + " close: " + closeStr) // Initialize points for BTCUSDT.P longPointsRSIBTC = close > close[1] ? 1 : 0 From ed545a1ddb2467d27208c657ad01b05519afbd76 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 12 Jan 2024 19:21:29 +0200 Subject: [PATCH 15/26] latest changes --- Niki/niki-refactored.pine | 92 ++++++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 26 deletions(-) diff --git a/Niki/niki-refactored.pine b/Niki/niki-refactored.pine index aa88fc5..646c2c2 100644 --- a/Niki/niki-refactored.pine +++ b/Niki/niki-refactored.pine @@ -3,17 +3,40 @@ indicator("DrNiki's Market Nuker", shorttitle="DrNiki's Market Nuker", overlay=t // Function to calculate RSI rsiLength = input(14, title="RSI Length") -calcRSI() => ta.rsi(close, rsiLength) - -// Function to calculate Stochastic RSI stochRsiLength = input(14, title="Stochastic RSI Length") -calcStochRSI() => ta.stoch(close, close, close, stochRsiLength) - -// Function to calculate Wavetrend n1 = input(10, "Channel Length") n2 = input(21, "Average Length") -calcWavetrend() => - ap = hlc3 +mfiLength = input(7, title="MFI Length") + + +// calcRSI() => ta.rsi(close, rsiLength) +// // Function to calculate Stochastic RSI +// calcStochRSI() => ta.stoch(close, close, close, stochRsiLength) +// // Function to calculate Wavetrend +// calcWavetrend() => +// ap = hlc3 +// esa = ta.ema(ap, n1) +// d = ta.ema(math.abs(ap - esa), n1) +// ci = (ap - esa) / (0.015 * d) +// tci = ta.ema(ci, n2) +// wt1 = tci +// wt2 = ta.sma(wt1, 4) +// [wt1, wt2] + +// // Function to calculate On Balance Volume (OBV) +// calcOBV() => +// var float obv = na +// obv := close > close[1] ? obv + volume : close < close[1] ? obv - volume : obv +// obv + +// // Function to calculate MFI +// calcMFI() => ta.mfi(close, mfiLength) + + +calcRSI(source) => ta.rsi(source, rsiLength) +calcStochRSI(source) => ta.stoch(source, source, source, stochRsiLength) +calcWavetrend(source) => + ap = source esa = ta.ema(ap, n1) d = ta.ema(math.abs(ap - esa), n1) ci = (ap - esa) / (0.015 * d) @@ -22,23 +45,20 @@ calcWavetrend() => wt2 = ta.sma(wt1, 4) [wt1, wt2] -// Function to calculate On Balance Volume (OBV) -calcOBV() => +calcOBV(source, volumeSource) => var float obv = na obv := close > close[1] ? obv + volume : close < close[1] ? obv - volume : obv obv -// Function to calculate MFI -mfiLength = input(7, title="MFI Length") -calcMFI() => ta.mfi(close, mfiLength) +calcMFI(source) => ta.mfi(source, mfiLength) // Function to calculate points for a symbol calcPoints(symbol) => - rsiValue = calcRSI() - stochRsiValue = calcStochRSI() - [wt1, wt2] = calcWavetrend() - obv = calcOBV() - mfiValue = calcMFI() + rsiValue = request.security(symbol, timeframe.period, calcRSI(close), barmerge.gaps_off, barmerge.lookahead_on) + stochRsiValue = request.security(symbol, timeframe.period, calcStochRSI(close), barmerge.gaps_off, barmerge.lookahead_on) + [wt1, wt2] = request.security(symbol, timeframe.period, calcWavetrend(close), barmerge.gaps_off, barmerge.lookahead_on) + obv = request.security(symbol, timeframe.period, calcOBV(close, volume), barmerge.gaps_off, barmerge.lookahead_on) + mfiValue = request.security(symbol, timeframe.period, calcMFI(close), barmerge.gaps_off, barmerge.lookahead_on) longPoints = 0 shortPoints = 0 @@ -58,22 +78,39 @@ calcPoints(symbol) => // Symbols array symbols = array.new_string(5) -array.set(symbols, 0, syminfo.tickerid) +array.set(symbols, 0, syminfo.ticker) // Replace with the symbol of your chart array.set(symbols, 1, "GOLD") array.set(symbols, 2, "DXY") array.set(symbols, 3, "BTCUSDT.P") -array.set(symbols, 4, "US30" ) +array.set(symbols, 4, "US30") + + +var string[] list = array.from(syminfo.ticker, "GOLD", "DXY", "BTCUSDT.P", "US30") +var string sym = "" + +for i in list + log.info(i) + [longPoints, shortPoints] = calcPoints(i) + sym := i + " " + var logMessage = "| sym: " + sym + " " + i + barTimeStr = str.format_time(time, "yyyy-MM-dd HH:mm:ss", "Europe/Sofia") + log.info(logMessage) + +log.info("-------------------------") // Calculate points for each symbol var symbolPoints = array.new_int(size=array.size(symbols) * 2, initial_value=0) -for symbol in symbols - // Change symbol context using security() function - [longPoints, shortPoints] = calcPoints(symbol) +for i in list + var sm = i +" " barTimeStr = str.format_time(time, "yyyy-MM-dd HH:mm:ss", "Europe/Sofia") - var logMessage = barTimeStr + "| Symbol: " + symbol + ", Long: " + str.tostring(longPoints) + ", Short: " + str.tostring(shortPoints) + var logMessage = barTimeStr + "| Symbol: " + i + "sm: " + sm log.info(logMessage) - array.set(symbolPoints, 0, array.get(symbolPoints, 0) + longPoints) - array.set(symbolPoints, 1, array.get(symbolPoints, 1) + shortPoints) + //rsiValue = request.security(symbol, timeframe.period, calcRSI(close), barmerge.gaps_off, barmerge.lookahead_on) + + // Change symbol context using security() function + // [longPoints, shortPoints] = calcPoints(symbol.symbol) + // array.set(symbolPoints, 0, array.get(symbolPoints, 0) + longPoints) + // array.set(symbolPoints, 1, array.get(symbolPoints, 1) + shortPoints) // Calculate total long and short probabilities totalLongPoints = array.get(symbolPoints, 0) @@ -87,3 +124,6 @@ label.set_xy(labelBox, bar_index, high) label.set_text(labelBox, "Combined Probabilities\nLong: " + str.tostring(combinedProbabilityLong) + "%\nShort: " + str.tostring(combinedProbabilityShort) + "%") label.set_color(labelBox, color.new(color.blue, 0)) label.set_style(labelBox, label.style_label_left) + + + From 20935610469ea5c8043d7f363f4ef0bf420a7ec4 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 12 Jan 2024 20:06:06 +0200 Subject: [PATCH 16/26] niki new --- Niki/niki2.pine | 80 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 Niki/niki2.pine diff --git a/Niki/niki2.pine b/Niki/niki2.pine new file mode 100644 index 0000000..6e68f3c --- /dev/null +++ b/Niki/niki2.pine @@ -0,0 +1,80 @@ +//@version=5 +indicator("DrNiki's Market Nuker", shorttitle="DrNiki's Market Nuker", overlay=true) + +// Function to calculate RSI +rsiLength = input(14, title="RSI Length") +rsiValue = ta.rsi(close, rsiLength) + +// Stochastic RSI +stochRsiLength = input(14, title="Stochastic RSI Length") +stochRsiValue = ta.stoch(close, close, close, stochRsiLength) + +// Wavetrend Indicator +n1 = input(10, "Channel Length") +n2 = input(21, "Average Length") +obLevel1 = input(60, "Over Bought Level 1") +obLevel2 = input(53, "Over Bought Level 2") +osLevel1 = input(-60, "Over Sold Level 1") +osLevel2 = input(-53, "Over Sold Level 2") + +ap = hlc3 +esa = ta.ema(ap, n1) +d = ta.ema(math.abs(ap - esa), n1) +ci = (ap - esa) / (0.015 * d) +tci = ta.ema(ci, n2) + +wt1 = tci +wt2 = ta.sma(wt1, 4) + +// Custom implementation of On Balance Volume (OBV) +var float obv = na +obv := close > close[1] ? obv + volume : close < close[1] ? obv - volume : obv + +// Money Flow Index (MFI) +mfiLength = input(7, title="MFI Length") +mfiValue = ta.mfi(close, mfiLength) + +// Initialize points for each timeframe +longPointsRSI = close > close[1] ? 1 : 0 +shortPointsRSI = close < close[1] ? 1 : 0 +longPointsStochRSI = stochRsiValue > stochRsiValue[1] ? 1 : 0 +shortPointsStochRSI = stochRsiValue < stochRsiValue[1] ? 1 : 0 +longPointsWavetrend = wt1 > wt1[1] ? 1 : 0 +shortPointsWavetrend = wt1 < wt1[1] ? 1 : 0 +longPointsOBV = obv > obv[1] ? 1 : 0 +shortPointsOBV = obv < obv[1] ? 1 : 0 +longPointsMFI = mfiValue > 50 ? 1 : 0 +shortPointsMFI = mfiValue < 50 ? 1 : 0 + +// Calculate total points for each timeframe +totalLongPoints = longPointsRSI + longPointsStochRSI + longPointsWavetrend + longPointsOBV + longPointsMFI +totalShortPoints = shortPointsRSI + shortPointsStochRSI + shortPointsWavetrend + shortPointsOBV + shortPointsMFI + +// Calculate combined probabilities for each timeframe +combinedProbabilityLong = totalLongPoints / 5 * 100 +combinedProbabilityShort = totalShortPoints / 5 * 100 + +// Display combined probabilities in a box at the top right corner +var labelBox = label.new(na, na, "") +label.set_xy(labelBox, bar_index, high) +label.set_text(labelBox, "Long: " + str.tostring(combinedProbabilityLong) + "%\nShort: " + str.tostring(combinedProbabilityShort) + "%") +label.set_color(labelBox, color.new(color.blue, 0)) +label.set_style(labelBox, label.style_label_left) + +// Display on different timeframes +rsiValue1H = ta.rsi(close, 14) +rsiValue2H = ta.rsi(close, 28) +rsiValue3H = ta.rsi(close, 42) +rsiValue4H = ta.rsi(close, 56) + +// Odds calculation for each timeframe +odds1H = (longPointsRSI + longPointsStochRSI + longPointsWavetrend + longPointsOBV + longPointsMFI) / 5 * 100 +odds2H = (shortPointsRSI + shortPointsStochRSI + shortPointsWavetrend + shortPointsOBV + shortPointsMFI) / 5 * 100 +odds3H = (longPointsRSI + longPointsStochRSI + longPointsWavetrend + longPointsOBV + longPointsMFI) / 5 * 100 +odds4H = (shortPointsRSI + shortPointsStochRSI + shortPointsWavetrend + shortPointsOBV + shortPointsMFI) / 5 * 100 + +// Plotting +plot(rsiValue1H, title="RSI 1H", color=color.new(color.red, 0), linewidth=2) +plot(rsiValue2H, title="RSI 2H", color=color.new(color.blue, 0), linewidth=2) +plot(rsiValue3H, title="RSI 3H", color=color.new(color.green, 0), linewidth=2) +plot(rsiValue4H, title="RSI 4H", color=color.new(color.purple, 0), linewidth=2) \ No newline at end of file From 4078ed67fec1c370499bb8577328fe45923edbf1 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Mon, 15 Jan 2024 14:38:06 +0000 Subject: [PATCH 17/26] niki's update --- Niki/niki.pine | 217 ++++++++++++++++++--------------------------- Niki/old/new.pine | 93 +++++++++++++++++++ Niki/old/niki.pine | 151 +++++++++++++++++++++++++++++++ 3 files changed, 332 insertions(+), 129 deletions(-) create mode 100644 Niki/old/new.pine create mode 100644 Niki/old/niki.pine diff --git a/Niki/niki.pine b/Niki/niki.pine index 28c00b4..47f74f5 100644 --- a/Niki/niki.pine +++ b/Niki/niki.pine @@ -1,152 +1,111 @@ //@version=5 -indicator("DrNiki's Market Nuker", shorttitle="DrNiki's Market Nuker", overlay=true) +indicator("Divergence Odds Calculator", shorttitle="DrNiki DivOdds", overlay=true) -// Relative Strength Index (RSI) +// Function to detect bullish divergence +bullishDivergence(src, refSrc, rsiSrc, overboughtLevel, oversoldLevel) => + priceHigh = ta.highest(src, 5) + rsiHigh = ta.highest(rsiSrc, 5) + priceLow = ta.lowest(src, 5) + rsiLow = ta.lowest(rsiSrc, 5) + + priceDiv = (src > priceHigh[1] and rsiSrc > rsiHigh[1]) ? true : false + rsiDiv = (rsiSrc > rsiHigh[1] and src > priceHigh[1]) ? true : false + + priceDiv or rsiDiv + +// Function to detect bearish divergence +bearishDivergence(src, refSrc, rsiSrc, overboughtLevel, oversoldLevel) => + priceHigh = ta.highest(src, 5) + rsiHigh = ta.highest(rsiSrc, 5) + priceLow = ta.lowest(src, 5) + rsiLow = ta.lowest(rsiSrc, 5) + + priceDiv = (src < priceLow[1] and rsiSrc < rsiLow[1]) ? true : false + rsiDiv = (rsiSrc < rsiLow[1] and src < priceLow[1]) ? true : false + + priceDiv or rsiDiv + +// RSI settings rsiLength = input(14, title="RSI Length") -rsiValue = ta.rsi(close, rsiLength) +rsiOverbought = input(70, title="RSI Overbought Level") +rsiOversold = input(30, title="RSI Oversold Level") +rsiSrc = ta.rsi(close, rsiLength) -// Stochastic RSI -stochRsiLength = input(14, title="Stochastic RSI Length") -stochRsiValue = ta.stoch(close, close, close, stochRsiLength) +// Calculate the number of occurrences of bullish and bearish divergences for different periods +bullishCount1 = ta.barssince(bullishDivergence(close, close[1], rsiSrc, rsiOverbought, rsiOversold))[1] + 1 +bearishCount1 = ta.barssince(bearishDivergence(close, close[1], rsiSrc, rsiOverbought, rsiOversold))[1] + 1 -// Wavetrend Indicator -n1 = input(10, "Channel Length") -n2 = input(21, "Average Length") -obLevel1 = input(60, "Over Bought Level 1") -obLevel2 = input(53, "Over Bought Level 2") -osLevel1 = input(-60, "Over Sold Level 1") -osLevel2 = input(-53, "Over Sold Level 2") +bullishCount2 = ta.barssince(bullishDivergence(close, close[1], rsiSrc, rsiOverbought, rsiOversold))[2] + 1 +bearishCount2 = ta.barssince(bearishDivergence(close, close[1], rsiSrc, rsiOverbought, rsiOversold))[2] + 1 -ap = hlc3 -esa = ta.ema(ap, n1) -d = ta.ema(math.abs(ap - esa), n1) -ci = (ap - esa) / (0.015 * d) -tci = ta.ema(ci, n2) +bullishCount3 = ta.barssince(bullishDivergence(close, close[1], rsiSrc, rsiOverbought, rsiOversold))[3] + 1 +bearishCount3 = ta.barssince(bearishDivergence(close, close[1], rsiSrc, rsiOverbought, rsiOversold))[3] + 1 -wt1 = tci -wt2 = ta.sma(wt1, 4) +bullishCount5 = ta.barssince(bullishDivergence(close, close[1], rsiSrc, rsiOverbought, rsiOversold))[5] + 1 +bearishCount5 = ta.barssince(bearishDivergence(close, close[1], rsiSrc, rsiOverbought, rsiOversold))[5] + 1 -// Custom implementation of On Balance Volume (OBV) -var float obv = na -obv := close > close[1] ? obv + volume : close < close[1] ? obv - volume : obv +bullishCount10 = ta.barssince(bullishDivergence(close, close[1], rsiSrc, rsiOverbought, rsiOversold))[10] + 1 +bearishCount10 = ta.barssince(bearishDivergence(close, close[1], rsiSrc, rsiOverbought, rsiOversold))[10] + 1 -// Money Flow Index (MFI) -mfiLength = input(7, title="MFI Length") -mfiValue = ta.mfi(close, mfiLength) +bullishCount20 = ta.barssince(bullishDivergence(close, close[1], rsiSrc, rsiOverbought, rsiOversold))[20] + 1 +bearishCount20 = ta.barssince(bearishDivergence(close, close[1], rsiSrc, rsiOverbought, rsiOversold))[20] + 1 +// Calculate odds based on the occurrences of divergences +calcOdds(count, candles) => + odds = (count / candles) * 100 + odds -var logMessage = barTimeStr + "| Symbol: " + symbol + ", Long: " + str.tostring(longPoints) + ", Short: " + str.tostring(shortPoints) -log.info(logMessage) +// Normalize probabilities so they add up to 100% +normalizeProbabilities(bullish, bearish) => + total = bullish + bearish + bullishProb = (bullish / total) * 100 + bearishProb = (bearish / total) * 100 + [bullishProb, bearishProb] -barTimeStr = str.format_time(time, "yyyy-MM-dd HH:mm:ss", "Europe/Sofia") -closeStr = str.tostring(close) -log.info(barTimeStr + " close: " + closeStr) +// Calculate odds for different candle periods +[bullishOdds1, bearishOdds1] = normalizeProbabilities(calcOdds(bullishCount1, 1), calcOdds(bearishCount1, 1)) +[bullishOdds2, bearishOdds2] = normalizeProbabilities(calcOdds(bullishCount2, 2), calcOdds(bearishCount2, 2)) +[bullishOdds3, bearishOdds3] = normalizeProbabilities(calcOdds(bullishCount3, 3), calcOdds(bearishCount3, 3)) +[bullishOdds5, bearishOdds5] = normalizeProbabilities(calcOdds(bullishCount5, 5), calcOdds(bearishCount5, 5)) +[bullishOdds10, bearishOdds10] = normalizeProbabilities(calcOdds(bullishCount10, 10), calcOdds(bearishCount10, 10)) +[bullishOdds20, bearishOdds20] = normalizeProbabilities(calcOdds(bullishCount20, 20), calcOdds(bearishCount20, 20)) -// Initialize points for BTCUSDT.P -longPointsRSIBTC = close > close[1] ? 1 : 0 -shortPointsRSIBTC = close < close[1] ? 1 : 0 -longPointsStochRSIBTC = stochRsiValue > stochRsiValue[1] ? 1 : 0 -shortPointsStochRSIBTC = stochRsiValue < stochRsiValue[1] ? 1 : 0 -longPointsWavetrendBTC = wt1 > wt1[1] ? 1 : 0 -shortPointsWavetrendBTC = wt1 < wt1[1] ? 1 : 0 -longPointsOBVBTC = obv > obv[1] ? 1 : 0 -shortPointsOBVBTC = obv < obv[1] ? 1 : 0 -longPointsMFIBTC = mfiValue > 50 ? 1 : 0 -shortPointsMFIBTC = mfiValue < 50 ? 1 : 0 +// Calculate total odds for the selected candle periods +totalBullishOdds = bullishOdds1 + bullishOdds2 + bullishOdds3 + bullishOdds5 + bullishOdds10 + bullishOdds20 +totalBearishOdds = bearishOdds1 + bearishOdds2 + bearishOdds3 + bearishOdds5 + bearishOdds10 + bearishOdds20 -// Initialize points for DXY -longPointsRSIDXY = close > close[1] ? 0 : 1 -shortPointsRSIDXY = close < close[1] ? 0 : 1 -longPointsStochRSIDXY = stochRsiValue > stochRsiValue[1] ? 0 : 1 -shortPointsStochRSIDXY = stochRsiValue < stochRsiValue[1] ? 0 : 1 -longPointsWavetrendDXY = wt1 < wt1[1] ? 0 : 1 -shortPointsWavetrendDXY = wt1 > wt1[1] ? 0 : 1 -longPointsOBVDXY = obv > obv[1] ? 0 : 1 -shortPointsOBVDXY = obv < obv[1] ? 0 : 1 -longPointsMFIDXY = mfiValue > 50 ? 0 : 1 -shortPointsMFIDXY = mfiValue < 50 ? 0 : 1 +// New totals +totalBullishOdds1_2 = bullishOdds1 + bullishOdds2 +totalBullishOdds1_2_3 = totalBullishOdds1_2 + bullishOdds3 +totalBullishOdds1_2_3_5 = totalBullishOdds1_2_3 + bullishOdds5 -// Initialize points for GOLD -longPointsRSIGOLD = close > close[1] ? 1 : 0 -shortPointsRSIGOLD = close < close[1] ? 1 : 0 -longPointsStochRSIGOLD = stochRsiValue > stochRsiValue[1] ? 1 : 0 -shortPointsStochRSIGOLD = stochRsiValue < stochRsiValue[1] ? 1 : 0 -longPointsWavetrendGOLD = wt1 > wt1[1] ? 1 : 0 -shortPointsWavetrendGOLD = wt1 < wt1[1] ? 1 : 0 -longPointsOBVGOLD = obv > obv[1] ? 1 : 0 -shortPointsOBVGOLD = obv < obv[1] ? 1 : 0 -longPointsMFIGOLD = mfiValue > 50 ? 1 : 0 -shortPointsMFIGOLD = mfiValue < 50 ? 1 : 0 +totalBearishOdds1_2 = bearishOdds1 + bearishOdds2 +totalBearishOdds1_2_3 = totalBearishOdds1_2 + bearishOdds3 +totalBearishOdds1_2_3_5 = totalBearishOdds1_2_3 + bearishOdds5 +// Display odds information in a label +var labelOdds = label.new(na, na, "") +label.set_xy(labelOdds, bar_index, high) +label.set_text(labelOdds, "Odds:\nLast 1 Candle: Bullish " + str.tostring(bullishOdds1) + "%, Bearish " + str.tostring(bearishOdds1) + "%\nLast 2 Candles: Bullish " + str.tostring(bullishOdds2) + "%, Bearish " + str.tostring(bearishOdds2) + "%\nLast 3 Candles: Bullish " + str.tostring(bullishOdds3) + "%, Bearish " + str.tostring(bearishOdds3) + "%\nLast 5 Candles: Bullish " + str.tostring(bullishOdds5) + "%, Bearish " + str.tostring(bearishOdds5) + "%\nLast 10 Candles: Bullish " + str.tostring(bullishOdds10) + "%, Bearish " + str.tostring(bearishOdds10) + "%\nLast 20 Candles: Bullish " + str.tostring(bullishOdds20) + "%, Bearish " + str.tostring(bearishOdds20) + "%\nTotal: Bullish " + str.tostring(totalBullishOdds) + "%, Bearish " + str.tostring(totalBearishOdds) + "%\n\nNew Totals:\nTotal 1-2: Bullish " + str.tostring(totalBullishOdds1_2) + "%, Bearish " + str.tostring(totalBearishOdds1_2) + "%\nTotal 1-2-3: Bullish " + str.tostring(totalBullishOdds1_2_3) + "%, Bearish " + str.tostring(totalBearishOdds1_2_3) + "%\nTotal 1-2-3-5: Bullish " + str.tostring(totalBullishOdds1_2_3_5) + "%, Bearish " + str.tostring(totalBearishOdds1_2_3_5) + "%") +label.set_color(labelOdds, totalBullishOdds > totalBearishOdds ? color.new(color.green, 0) : color.new(color.red, 0)) +label.set_style(labelOdds, label.style_label_left) -// Initialize points for US30 -longPointsRSIUS30 = close > close[1] ? 1 : 0 -shortPointsRSIUS30 = close < close[1] ? 1 : 0 -longPointsStochRSIUS30 = stochRsiValue > stochRsiValue[1] ? 1 : 0 -shortPointsStochRSIUS30 = stochRsiValue < stochRsiValue[1] ? 1 : 0 -longPointsWavetrendUS30 = wt1 > wt1[1] ? 1 : 0 -shortPointsWavetrendUS30 = wt1 < wt1[1] ? 1 : 0 -longPointsOBVUS30 = obv > obv[1] ? 1 : 0 -shortPointsOBVUS30 = obv < obv[1] ? 1 : 0 -longPointsMFIUS30 = mfiValue > 50 ? 1 : 0 -shortPointsMFIUS30 = mfiValue < 50 ? 1 : 0 +// Plotting +plot(rsiSrc, title="RSI", color=color.new(color.blue, 0), linewidth=2) -// Initialize points for the current trading pair (syminfo.ticker) -longPointsRSIPAIR = close > close[1] ? 1 : 0 -shortPointsRSIPAIR = close < close[1] ? 1 : 0 -longPointsStochRSIPAIR = stochRsiValue > stochRsiValue[1] ? 1 : 0 -shortPointsStochRSIPAIR = stochRsiValue < stochRsiValue[1] ? 1 : 0 -longPointsWavetrendPAIR = wt1 > wt1[1] ? 1 : 0 -shortPointsWavetrendPAIR = wt1 < wt1[1] ? 1 : 0 -longPointsOBVPAIR = obv > obv[1] ? 1 : 0 -shortPointsOBVPAIR = obv < obv[1] ? 1 : 0 -longPointsMFIPAIR = mfiValue > 50 ? 1 : 0 -shortPointsMFIPAIR = mfiValue < 50 ? 1 : 0 +// Plot green flag if total bullish odds are 5 times higher than bearish odds +plotshape(totalBullishOdds > 5 * totalBearishOdds, style=shape.triangleup, location=location.belowbar, color=color.new(color.green, 0), size=size.small) -// Calculate total points for each symbol -totalLongPointsBTC = longPointsRSIBTC + longPointsStochRSIBTC + longPointsWavetrendBTC -totalShortPointsBTC = shortPointsRSIBTC + shortPointsStochRSIBTC + shortPointsWavetrendBTC +// Plot red flag if total bearish odds are 5 times higher than bullish odds +plotshape(totalBearishOdds > 5 * totalBullishOdds, style=shape.triangledown, location=location.belowbar, color=color.new(color.red, 0), size=size.small) -totalLongPointsGOLD = longPointsRSIGOLD + longPointsStochRSIGOLD + longPointsWavetrendGOLD -totalShortPointsGOLD = shortPointsRSIGOLD + shortPointsStochRSIGOLD + shortPointsWavetrendGOLD +// Plot diamond if total bullish odds are 6 times higher than bearish odds +plotshape(totalBullishOdds > 6 * totalBearishOdds, style=shape.diamond, location=location.belowbar, color=color.new(color.blue, 0), size=size.small) -totalLongPointsDXY = longPointsRSIDXY + longPointsStochRSIDXY + longPointsWavetrendDXY -totalShortPointsDXY = shortPointsRSIDXY + shortPointsStochRSIDXY + shortPointsWavetrendDXY +// Plot diamond if total bearish odds are 6 times higher than bullish odds +plotshape(totalBearishOdds > 6 * totalBullishOdds, style=shape.diamond, location=location.belowbar, color=color.new(color.purple, 0), size=size.small) -totalLongPointsUS30 = longPointsRSIUS30 + longPointsStochRSIUS30 + longPointsWavetrendUS30 -totalShortPointsUS30 = shortPointsRSIUS30 + shortPointsStochRSIUS30 + shortPointsWavetrendUS30 - -totalLongPointsPAIR = longPointsRSIPAIR + longPointsStochRSIPAIR + longPointsWavetrendPAIR -totalShortPointsPAIR = shortPointsRSIPAIR + shortPointsStochRSIPAIR + shortPointsWavetrendPAIR - -// Calculate total long and short probabilities for all symbols -totalLongPoints = totalLongPointsBTC + totalLongPointsDXY + totalLongPointsGOLD + totalLongPointsUS30 + totalLongPointsPAIR -totalShortPoints = totalShortPointsBTC + totalShortPointsDXY + totalShortPointsGOLD + totalShortPointsUS30 + totalShortPointsPAIR - -// Calculate combined probabilities for each symbol -combinedProbabilityLongBTC = totalLongPointsBTC / 3 * 100 -combinedProbabilityShortBTC = totalShortPointsBTC / 3 * 100 - -combinedProbabilityLongDXY = totalLongPointsDXY / 3 * 100 -combinedProbabilityShortDXY = totalShortPointsDXY / 3 * 100 - -combinedProbabilityLongGOLD = totalLongPointsGOLD / 3 * 100 -combinedProbabilityShortGOLD = totalShortPointsGOLD / 3 * 100 - -combinedProbabilityLongUS30 = totalLongPointsUS30 / 3 * 100 -combinedProbabilityShortUS30 = totalShortPointsUS30 / 3 * 100 - -combinedProbabilityLongPAIR = totalLongPointsPAIR / 3 * 100 -combinedProbabilityShortPAIR = totalShortPointsPAIR / 3 * 100 - -// Calculate combined probabilities for all symbols -combinedProbabilityLong = totalLongPoints / 15 * 100 -combinedProbabilityShort = totalShortPoints / 15 * 100 - -// Display combined probabilities in a box at the top right corner -var labelBox = label.new(na, na, "") -label.set_xy(labelBox, bar_index, high) -label.set_text(labelBox, "Long: BTC " + str.tostring(combinedProbabilityLongBTC) + "%, DXY " + str.tostring(combinedProbabilityLongDXY) + "%, GOLD " + str.tostring(combinedProbabilityLongGOLD) + "%, US30 " + str.tostring(combinedProbabilityLongUS30) + "%, syminfo.ticker " + str.tostring(combinedProbabilityLongPAIR) + "%\nShort: BTC " + str.tostring(combinedProbabilityShortBTC) + "%, DXY " + str.tostring(combinedProbabilityShortDXY) + "%, GOLD " + str.tostring(combinedProbabilityShortGOLD) + "%, US30 " + str.tostring(combinedProbabilityShortUS30) + "%, syminfo.ticker " + str.tostring(combinedProbabilityShortPAIR) + "%\n\nTotal: Long " + str.tostring(combinedProbabilityLong) + "%, Short " + str.tostring(combinedProbabilityShort) + "%") -label.set_color(labelBox, color.new(color.blue, 0)) -label.set_style(labelBox, label.style_label_left) +// Plot green flag for previous occurrences if total bullish odds are 5 times higher than bearish odds +plotshape(totalBullishOdds[1] > 5 * totalBearishOdds[1], style=shape.triangleup, location=location.belowbar, color=color.new(color.green, 0), size=size.small) +// Plot red \ No newline at end of file diff --git a/Niki/old/new.pine b/Niki/old/new.pine new file mode 100644 index 0000000..8fc01b7 --- /dev/null +++ b/Niki/old/new.pine @@ -0,0 +1,93 @@ +//@version=5 +indicator("DrNiki's Market Nuker", shorttitle="DrNiki's Market Nuker", overlay=true) + +// Function to calculate RSI +rsiLength = input(14, title="RSI Length") +calcRSI() => ta.rsi(close, rsiLength) + +// Function to calculate Stochastic RSI +stochRsiLength = input(14, title="Stochastic RSI Length") +calcStochRSI() => ta.stoch(close, close, close, stochRsiLength) + +// Function to calculate Wavetrend +n1 = input(10, "Channel Length") +n2 = input(21, "Average Length") +calcWavetrend() => + ap = hlc3 + esa = ta.ema(ap, n1) + d = ta.ema(math.abs(ap - esa), n1) + ci = (ap - esa) / (0.015 * d) + tci = ta.ema(ci, n2) + wt1 = tci + wt2 = ta.sma(wt1, 4) + [wt1, wt2] + +// Function to calculate On Balance Volume (OBV) +calcOBV() => + var float obv = na + obv := close > close[1] ? obv + volume : close < close[1] ? obv - volume : obv + obv + +// Function to calculate MFI +mfiLength = input(7, title="MFI Length") +calcMFI() => ta.mfi(close, mfiLength) + +// Function to calculate points for a symbol +calcPoints(symbol) => + rsiValue = calcRSI() + stochRsiValue = calcStochRSI() + [wt1, wt2] = calcWavetrend() + obv = calcOBV() + mfiValue = calcMFI() + + longPoints = 0 + shortPoints = 0 + longPoints := rsiValue > rsiValue[1] ? longPoints + 1 : longPoints + shortPoints := rsiValue < rsiValue[1] ? shortPoints + 1 : shortPoints + longPoints := stochRsiValue > stochRsiValue[1] ? longPoints + 1 : longPoints + shortPoints := stochRsiValue < stochRsiValue[1] ? shortPoints + 1 : shortPoints + longPoints := wt1 > wt1[1] ? longPoints + 1 : longPoints + shortPoints := wt1 < wt1[1] ? shortPoints + 1 : shortPoints + longPoints := obv > obv[1] ? longPoints + 1 : longPoints + shortPoints := obv < obv[1] ? shortPoints + 1 : shortPoints + longPoints := mfiValue > 50 ? longPoints + 1 : longPoints + shortPoints := mfiValue < 50 ? shortPoints + 1 : shortPoints + var logMessage = "Symbol: " + symbol + ", RSI: " + str.tostring(rsiValue) + + ", StochRSI: " + str.tostring(stochRsiValue) + + ", WT1: " + str.tostring(wt1) + + ", OBV: " + str.tostring(obv) + + ", MFI: " + str.tostring(mfiValue) + + ", Long: " + str.tostring(longPoints) + ", Short: " + str.tostring(shortPoints) + log.info(logMessage) + [longPoints, shortPoints] + +// Symbols array +symbols = array.new_string(5) +array.set(symbols, 0, syminfo.tickerid) +array.set(symbols, 1, "GOLD") +array.set(symbols, 2, "DXY") +array.set(symbols, 3, "BTCUSDT.P") +array.set(symbols, 4, "US30" ) + +// Calculate points for each symbol +var symbolPoints = array.new_int(2, 0) +for symbol in symbols + // Change symbol context using security() function + [longPoints, shortPoints] = calcPoints(symbol) + var logMessage = "Symbol: " + symbol + ", Long: " + str.tostring(longPoints) + ", Short: " + str.tostring(shortPoints) + log.info(logMessage) + array.set(symbolPoints, 0, array.get(symbolPoints, 0) + longPoints) + array.set(symbolPoints, 1, array.get(symbolPoints, 1) + shortPoints) + +// Calculate total long and short probabilities +totalLongPoints = array.get(symbolPoints, 0) +totalShortPoints = array.get(symbolPoints, 1) +combinedProbabilityLong = totalLongPoints / (array.size(symbols) * 3) * 100 +combinedProbabilityShort = totalShortPoints / (array.size(symbols) * 3) * 100 + +// Display combined probabilities +var labelBox = label.new(na, na, "") +label.set_xy(labelBox, bar_index, high) +label.set_text(labelBox, "Combined Probabilities\nLong: " + str.tostring(combinedProbabilityLong) + "%\nShort: " + str.tostring(combinedProbabilityShort) + "%") +label.set_color(labelBox, color.new(color.blue, 0)) +label.set_style(labelBox, label.style_label_left) diff --git a/Niki/old/niki.pine b/Niki/old/niki.pine new file mode 100644 index 0000000..e9c0a91 --- /dev/null +++ b/Niki/old/niki.pine @@ -0,0 +1,151 @@ +//@version=5 +indicator("DrNiki's Market Nuker", shorttitle="DrNiki's Market Nuker", overlay=true) + +// Relative Strength Index (RSI) +rsiLength = input(14, title="RSI Length") +rsiValue = ta.rsi(close, rsiLength) + +// Stochastic RSI +stochRsiLength = input(14, title="Stochastic RSI Length") +stochRsiValue = ta.stoch(close, close, close, stochRsiLength) + +// Wavetrend Indicator +n1 = input(10, "Channel Length") +n2 = input(21, "Average Length") +obLevel1 = input(60, "Over Bought Level 1") +obLevel2 = input(53, "Over Bought Level 2") +osLevel1 = input(-60, "Over Sold Level 1") +osLevel2 = input(-53, "Over Sold Level 2") + +ap = hlc3 +esa = ta.ema(ap, n1) +d = ta.ema(math.abs(ap - esa), n1) +ci = (ap - esa) / (0.015 * d) +tci = ta.ema(ci, n2) + +wt1 = tci +wt2 = ta.sma(wt1, 4) + +// Custom implementation of On Balance Volume (OBV) +var float obv = na +obv := close > close[1] ? obv + volume : close < close[1] ? obv - volume : obv + +// Money Flow Index (MFI) +mfiLength = input(7, title="MFI Length") +mfiValue = ta.mfi(close, mfiLength) + + + +// Initialize points for BTCUSDT.P +longPointsRSIBTC = close > close[1] ? 1 : 0 +shortPointsRSIBTC = close < close[1] ? 1 : 0 +longPointsStochRSIBTC = stochRsiValue > stochRsiValue[1] ? 1 : 0 +shortPointsStochRSIBTC = stochRsiValue < stochRsiValue[1] ? 1 : 0 +longPointsWavetrendBTC = wt1 > wt1[1] ? 1 : 0 +shortPointsWavetrendBTC = wt1 < wt1[1] ? 1 : 0 +longPointsOBVBTC = obv > obv[1] ? 1 : 0 +shortPointsOBVBTC = obv < obv[1] ? 1 : 0 +longPointsMFIBTC = mfiValue > 50 ? 1 : 0 +shortPointsMFIBTC = mfiValue < 50 ? 1 : 0 +//log time and close +//log.info("close: " + str.tostring(close)) +// get time formatted +timeStr = time(timeframe.period, "YYYY-MM-DD HH:mm:ss") +log.info("time: " + str.tostring(time) + " close: " + str.tostring(close) + " longPointsRSIBTC: " + str.tostring(longPointsRSIBTC) + " shortPointsRSIBTC: " + str.tostring(shortPointsRSIBTC) + " longPointsStochRSIBTC: " + str.tostring(longPointsStochRSIBTC) + " shortPointsStochRSIBTC: " + str.tostring(shortPointsStochRSIBTC) + " longPointsWavetrendBTC: " + str.tostring(longPointsWavetrendBTC) + " shortPointsWavetrendBTC: " + str.tostring(shortPointsWavetrendBTC) + " longPointsOBVBTC: " + str.tostring(longPointsOBVBTC) + " shortPointsOBVBTC: " + str.tostring(shortPointsOBVBTC) + " longPointsMFIBTC: " + str.tostring(longPointsMFIBTC) + " shortPointsMFIBTC: " + str.tostring(shortPointsMFIBTC)) + +// Initialize points for DXY +longPointsRSIDXY = close > close[1] ? 0 : 1 +shortPointsRSIDXY = close < close[1] ? 0 : 1 +longPointsStochRSIDXY = stochRsiValue > stochRsiValue[1] ? 0 : 1 +shortPointsStochRSIDXY = stochRsiValue < stochRsiValue[1] ? 0 : 1 +longPointsWavetrendDXY = wt1 < wt1[1] ? 0 : 1 +shortPointsWavetrendDXY = wt1 > wt1[1] ? 0 : 1 +longPointsOBVDXY = obv > obv[1] ? 0 : 1 +shortPointsOBVDXY = obv < obv[1] ? 0 : 1 +longPointsMFIDXY = mfiValue > 50 ? 0 : 1 +shortPointsMFIDXY = mfiValue < 50 ? 0 : 1 + +// Initialize points for GOLD +longPointsRSIGOLD = close > close[1] ? 1 : 0 +shortPointsRSIGOLD = close < close[1] ? 1 : 0 +longPointsStochRSIGOLD = stochRsiValue > stochRsiValue[1] ? 1 : 0 +shortPointsStochRSIGOLD = stochRsiValue < stochRsiValue[1] ? 1 : 0 +longPointsWavetrendGOLD = wt1 > wt1[1] ? 1 : 0 +shortPointsWavetrendGOLD = wt1 < wt1[1] ? 1 : 0 +longPointsOBVGOLD = obv > obv[1] ? 1 : 0 +shortPointsOBVGOLD = obv < obv[1] ? 1 : 0 +longPointsMFIGOLD = mfiValue > 50 ? 1 : 0 +shortPointsMFIGOLD = mfiValue < 50 ? 1 : 0 + + +// Initialize points for US30 +longPointsRSIUS30 = close > close[1] ? 1 : 0 +shortPointsRSIUS30 = close < close[1] ? 1 : 0 +longPointsStochRSIUS30 = stochRsiValue > stochRsiValue[1] ? 1 : 0 +shortPointsStochRSIUS30 = stochRsiValue < stochRsiValue[1] ? 1 : 0 +longPointsWavetrendUS30 = wt1 > wt1[1] ? 1 : 0 +shortPointsWavetrendUS30 = wt1 < wt1[1] ? 1 : 0 +longPointsOBVUS30 = obv > obv[1] ? 1 : 0 +shortPointsOBVUS30 = obv < obv[1] ? 1 : 0 +longPointsMFIUS30 = mfiValue > 50 ? 1 : 0 +shortPointsMFIUS30 = mfiValue < 50 ? 1 : 0 + +// Initialize points for the current trading pair (syminfo.ticker) +longPointsRSIPAIR = close > close[1] ? 1 : 0 +shortPointsRSIPAIR = close < close[1] ? 1 : 0 +longPointsStochRSIPAIR = stochRsiValue > stochRsiValue[1] ? 1 : 0 +shortPointsStochRSIPAIR = stochRsiValue < stochRsiValue[1] ? 1 : 0 +longPointsWavetrendPAIR = wt1 > wt1[1] ? 1 : 0 +shortPointsWavetrendPAIR = wt1 < wt1[1] ? 1 : 0 +longPointsOBVPAIR = obv > obv[1] ? 1 : 0 +shortPointsOBVPAIR = obv < obv[1] ? 1 : 0 +longPointsMFIPAIR = mfiValue > 50 ? 1 : 0 +shortPointsMFIPAIR = mfiValue < 50 ? 1 : 0 + +// Calculate total points for each symbol +totalLongPointsBTC = longPointsRSIBTC + longPointsStochRSIBTC + longPointsWavetrendBTC +totalShortPointsBTC = shortPointsRSIBTC + shortPointsStochRSIBTC + shortPointsWavetrendBTC + +totalLongPointsGOLD = longPointsRSIGOLD + longPointsStochRSIGOLD + longPointsWavetrendGOLD +totalShortPointsGOLD = shortPointsRSIGOLD + shortPointsStochRSIGOLD + shortPointsWavetrendGOLD + +totalLongPointsDXY = longPointsRSIDXY + longPointsStochRSIDXY + longPointsWavetrendDXY +totalShortPointsDXY = shortPointsRSIDXY + shortPointsStochRSIDXY + shortPointsWavetrendDXY + +totalLongPointsUS30 = longPointsRSIUS30 + longPointsStochRSIUS30 + longPointsWavetrendUS30 +totalShortPointsUS30 = shortPointsRSIUS30 + shortPointsStochRSIUS30 + shortPointsWavetrendUS30 + +totalLongPointsPAIR = longPointsRSIPAIR + longPointsStochRSIPAIR + longPointsWavetrendPAIR +totalShortPointsPAIR = shortPointsRSIPAIR + shortPointsStochRSIPAIR + shortPointsWavetrendPAIR + +// Calculate total long and short probabilities for all symbols +totalLongPoints = totalLongPointsBTC + totalLongPointsDXY + totalLongPointsGOLD + totalLongPointsUS30 + totalLongPointsPAIR +totalShortPoints = totalShortPointsBTC + totalShortPointsDXY + totalShortPointsGOLD + totalShortPointsUS30 + totalShortPointsPAIR + +// Calculate combined probabilities for each symbol +combinedProbabilityLongBTC = totalLongPointsBTC / 3 * 100 +combinedProbabilityShortBTC = totalShortPointsBTC / 3 * 100 + +combinedProbabilityLongDXY = totalLongPointsDXY / 3 * 100 +combinedProbabilityShortDXY = totalShortPointsDXY / 3 * 100 + +combinedProbabilityLongGOLD = totalLongPointsGOLD / 3 * 100 +combinedProbabilityShortGOLD = totalShortPointsGOLD / 3 * 100 + +combinedProbabilityLongUS30 = totalLongPointsUS30 / 3 * 100 +combinedProbabilityShortUS30 = totalShortPointsUS30 / 3 * 100 + +combinedProbabilityLongPAIR = totalLongPointsPAIR / 3 * 100 +combinedProbabilityShortPAIR = totalShortPointsPAIR / 3 * 100 + +// Calculate combined probabilities for all symbols +combinedProbabilityLong = totalLongPoints / 15 * 100 +combinedProbabilityShort = totalShortPoints / 15 * 100 + +// Display combined probabilities in a box at the top right corner +var labelBox = label.new(na, na, "") +label.set_xy(labelBox, bar_index, high) +label.set_text(labelBox, "Long: BTC " + str.tostring(combinedProbabilityLongBTC) + "%, DXY " + str.tostring(combinedProbabilityLongDXY) + "%, GOLD " + str.tostring(combinedProbabilityLongGOLD) + "%, US30 " + str.tostring(combinedProbabilityLongUS30) + "%, syminfo.ticker " + str.tostring(combinedProbabilityLongPAIR) + "%\nShort: BTC " + str.tostring(combinedProbabilityShortBTC) + "%, DXY " + str.tostring(combinedProbabilityShortDXY) + "%, GOLD " + str.tostring(combinedProbabilityShortGOLD) + "%, US30 " + str.tostring(combinedProbabilityShortUS30) + "%, syminfo.ticker " + str.tostring(combinedProbabilityShortPAIR) + "%\n\nTotal: Long " + str.tostring(combinedProbabilityLong) + "%, Short " + str.tostring(combinedProbabilityShort) + "%") +label.set_color(labelBox, color.new(color.blue, 0)) +label.set_style(labelBox, label.style_label_left) + From 7bb857a38415c76ca8372ce5e0cc52323e0a11bd Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Mon, 29 Jan 2024 11:55:33 +0200 Subject: [PATCH 18/26] added openvoice container --- .gitignore | 4 +++- doc/packages notes environments.md | 2 ++ tts/openvoice/Dockerfile | 21 +++++++++++++++++++++ tts/openvoice/OpenVoice | 1 + tts/openvoice/compose.yml | 6 ++++++ tts/openvoice/install | 29 +++++++++++++++++++++++++++++ 6 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 doc/packages notes environments.md create mode 100644 tts/openvoice/Dockerfile create mode 160000 tts/openvoice/OpenVoice create mode 100644 tts/openvoice/compose.yml create mode 100644 tts/openvoice/install diff --git a/.gitignore b/.gitignore index 2c73ccf..29b21f7 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,6 @@ rec/* */__pycache__/* __pycache__ agent-py-bot/scrape/raw/summary_log.txt -agent-py-bot/scrape/raw/* \ No newline at end of file +agent-py-bot/scrape/raw/* +.aider* +tts/*.m4a diff --git a/doc/packages notes environments.md b/doc/packages notes environments.md new file mode 100644 index 0000000..4f30ee7 --- /dev/null +++ b/doc/packages notes environments.md @@ -0,0 +1,2 @@ +pip install autogenstudio +autogenstudio ui --8081 \ No newline at end of file diff --git a/tts/openvoice/Dockerfile b/tts/openvoice/Dockerfile new file mode 100644 index 0000000..4770898 --- /dev/null +++ b/tts/openvoice/Dockerfile @@ -0,0 +1,21 @@ +# Use an official Python runtime as a parent image +FROM python:3.8-slim + +# Set the working directory in the container +WORKDIR /app + +# Clone the repository +RUN apt-get update && \ + apt-get install -y git aria2 unzip && \ + git clone -b dev https://github.com/camenduru/OpenVoice /app && \ + aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/camenduru/OpenVoice/resolve/main/checkpoints_1226.zip -d /app -o checkpoints_1226.zip && \ + unzip /app/checkpoints_1226.zip -d /app + +# Install any needed packages +RUN pip install gradio==3.50.2 langid faster-whisper whisper-timestamped unidecode eng-to-ipa pypinyin cn2an + +# Make port available to the world outside this container +EXPOSE 7860 + +# Run openvoice_app.py when the container launches +CMD ["python", "openvoice_app.py", "--share"] diff --git a/tts/openvoice/OpenVoice b/tts/openvoice/OpenVoice new file mode 160000 index 0000000..e99197f --- /dev/null +++ b/tts/openvoice/OpenVoice @@ -0,0 +1 @@ +Subproject commit e99197fe5ed92167acb39fc50237791b088fe2f7 diff --git a/tts/openvoice/compose.yml b/tts/openvoice/compose.yml new file mode 100644 index 0000000..5fa86f8 --- /dev/null +++ b/tts/openvoice/compose.yml @@ -0,0 +1,6 @@ +version: '3' +services: + openvoice: + build: . + ports: + - "7860:7860" diff --git a/tts/openvoice/install b/tts/openvoice/install new file mode 100644 index 0000000..905e693 --- /dev/null +++ b/tts/openvoice/install @@ -0,0 +1,29 @@ +# experimental +conda create -n openvoice python=3.9 +conda activate openvoice +conda install pytorch==1.13.1 torchvision==0.14.1 torchaudio==0.13.1 pytorch-cuda=11.7 -c pytorch -c nvidia +pip install -r requirements.txt +# git clone https://github.com/myshell-ai/OpenVoice.git +!git clone -b dev https://github.com/camenduru/OpenVoice +%cd /content/OpenVoice + +!apt -y install -qq aria2 +!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/camenduru/OpenVoice/resolve/main/checkpoints_1226.zip -d /content -o checkpoints_1226.zip +!unzip /content/checkpoints_1226.zip + +!pip install -q gradio==3.50.2 langid faster-whisper whisper-timestamped unidecode eng-to-ipa pypinyin cn2an + +!python openvoice_app.py --share + +# colab: +%cd /content +!git clone -b dev https://github.com/camenduru/OpenVoice +%cd /content/OpenVoice + +!apt -y install -qq aria2 +!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/camenduru/OpenVoice/resolve/main/checkpoints_1226.zip -d /content -o checkpoints_1226.zip +!unzip /content/checkpoints_1226.zip + +!pip install -q gradio==3.50.2 langid faster-whisper whisper-timestamped unidecode eng-to-ipa pypinyin cn2an + +!python openvoice_app.py --share \ No newline at end of file From 8edaa4b937253c29acd3c83c4a1543ba4f99016e Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Wed, 14 Feb 2024 18:02:49 +0200 Subject: [PATCH 19/26] new mobile project --- agent-mobile/artimobile/.bundle/config | 2 + agent-mobile/artimobile/.eslintrc.js | 4 + agent-mobile/artimobile/.gitignore | 66 ++ agent-mobile/artimobile/.prettierrc.js | 7 + agent-mobile/artimobile/.watchmanconfig | 1 + agent-mobile/artimobile/App.tsx | 118 +++ agent-mobile/artimobile/Gemfile | 9 + agent-mobile/artimobile/README.md | 79 ++ .../artimobile/__tests__/App.test.tsx | 17 + .../artimobile/android/app/build.gradle | 119 +++ .../artimobile/android/app/debug.keystore | Bin 0 -> 2257 bytes .../artimobile/android/app/proguard-rules.pro | 10 + .../android/app/src/debug/AndroidManifest.xml | 9 + .../android/app/src/main/AndroidManifest.xml | 25 + .../main/java/com/artimobile/MainActivity.kt | 22 + .../java/com/artimobile/MainApplication.kt | 45 ++ .../res/drawable/rn_edit_text_material.xml | 36 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3056 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 5024 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2096 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2858 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4569 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 7098 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6464 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 10676 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9250 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 15523 bytes .../app/src/main/res/values/strings.xml | 3 + .../app/src/main/res/values/styles.xml | 9 + agent-mobile/artimobile/android/build.gradle | 21 + .../artimobile/android/gradle.properties | 41 ++ .../android/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 63721 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + agent-mobile/artimobile/android/gradlew | 249 +++++++ agent-mobile/artimobile/android/gradlew.bat | 92 +++ .../artimobile/android/settings.gradle | 4 + agent-mobile/artimobile/app.json | 4 + agent-mobile/artimobile/babel.config.js | 3 + agent-mobile/artimobile/index.js | 9 + agent-mobile/artimobile/ios/.xcode.env | 11 + agent-mobile/artimobile/ios/Podfile | 55 ++ .../ios/artimobile.xcodeproj/project.pbxproj | 684 ++++++++++++++++++ .../xcschemes/artimobile.xcscheme | 88 +++ .../artimobile/ios/artimobile/AppDelegate.h | 6 + .../artimobile/ios/artimobile/AppDelegate.mm | 31 + .../AppIcon.appiconset/Contents.json | 53 ++ .../artimobile/Images.xcassets/Contents.json | 6 + .../artimobile/ios/artimobile/Info.plist | 52 ++ .../ios/artimobile/LaunchScreen.storyboard | 47 ++ agent-mobile/artimobile/ios/artimobile/main.m | 10 + .../artimobile/ios/artimobileTests/Info.plist | 24 + .../ios/artimobileTests/artimobileTests.m | 66 ++ agent-mobile/artimobile/jest.config.js | 3 + agent-mobile/artimobile/metro.config.js | 11 + agent-mobile/artimobile/package.json | 36 + agent-mobile/artimobile/supervisord.pid | 1 + agent-mobile/artimobile/tsconfig.json | 3 + agent-mobile/docker.yml | 25 + agent-mobile/idea.md | 45 ++ 59 files changed, 2268 insertions(+) create mode 100644 agent-mobile/artimobile/.bundle/config create mode 100644 agent-mobile/artimobile/.eslintrc.js create mode 100644 agent-mobile/artimobile/.gitignore create mode 100644 agent-mobile/artimobile/.prettierrc.js create mode 100644 agent-mobile/artimobile/.watchmanconfig create mode 100644 agent-mobile/artimobile/App.tsx create mode 100644 agent-mobile/artimobile/Gemfile create mode 100644 agent-mobile/artimobile/README.md create mode 100644 agent-mobile/artimobile/__tests__/App.test.tsx create mode 100644 agent-mobile/artimobile/android/app/build.gradle create mode 100644 agent-mobile/artimobile/android/app/debug.keystore create mode 100644 agent-mobile/artimobile/android/app/proguard-rules.pro create mode 100644 agent-mobile/artimobile/android/app/src/debug/AndroidManifest.xml create mode 100644 agent-mobile/artimobile/android/app/src/main/AndroidManifest.xml create mode 100644 agent-mobile/artimobile/android/app/src/main/java/com/artimobile/MainActivity.kt create mode 100644 agent-mobile/artimobile/android/app/src/main/java/com/artimobile/MainApplication.kt create mode 100644 agent-mobile/artimobile/android/app/src/main/res/drawable/rn_edit_text_material.xml create mode 100644 agent-mobile/artimobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 agent-mobile/artimobile/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 agent-mobile/artimobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 agent-mobile/artimobile/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 agent-mobile/artimobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 agent-mobile/artimobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 agent-mobile/artimobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 agent-mobile/artimobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 agent-mobile/artimobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 agent-mobile/artimobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 agent-mobile/artimobile/android/app/src/main/res/values/strings.xml create mode 100644 agent-mobile/artimobile/android/app/src/main/res/values/styles.xml create mode 100644 agent-mobile/artimobile/android/build.gradle create mode 100644 agent-mobile/artimobile/android/gradle.properties create mode 100644 agent-mobile/artimobile/android/gradle/wrapper/gradle-wrapper.jar create mode 100644 agent-mobile/artimobile/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 agent-mobile/artimobile/android/gradlew create mode 100644 agent-mobile/artimobile/android/gradlew.bat create mode 100644 agent-mobile/artimobile/android/settings.gradle create mode 100644 agent-mobile/artimobile/app.json create mode 100644 agent-mobile/artimobile/babel.config.js create mode 100644 agent-mobile/artimobile/index.js create mode 100644 agent-mobile/artimobile/ios/.xcode.env create mode 100644 agent-mobile/artimobile/ios/Podfile create mode 100644 agent-mobile/artimobile/ios/artimobile.xcodeproj/project.pbxproj create mode 100644 agent-mobile/artimobile/ios/artimobile.xcodeproj/xcshareddata/xcschemes/artimobile.xcscheme create mode 100644 agent-mobile/artimobile/ios/artimobile/AppDelegate.h create mode 100644 agent-mobile/artimobile/ios/artimobile/AppDelegate.mm create mode 100644 agent-mobile/artimobile/ios/artimobile/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 agent-mobile/artimobile/ios/artimobile/Images.xcassets/Contents.json create mode 100644 agent-mobile/artimobile/ios/artimobile/Info.plist create mode 100644 agent-mobile/artimobile/ios/artimobile/LaunchScreen.storyboard create mode 100644 agent-mobile/artimobile/ios/artimobile/main.m create mode 100644 agent-mobile/artimobile/ios/artimobileTests/Info.plist create mode 100644 agent-mobile/artimobile/ios/artimobileTests/artimobileTests.m create mode 100644 agent-mobile/artimobile/jest.config.js create mode 100644 agent-mobile/artimobile/metro.config.js create mode 100644 agent-mobile/artimobile/package.json create mode 100644 agent-mobile/artimobile/supervisord.pid create mode 100644 agent-mobile/artimobile/tsconfig.json create mode 100644 agent-mobile/docker.yml create mode 100644 agent-mobile/idea.md diff --git a/agent-mobile/artimobile/.bundle/config b/agent-mobile/artimobile/.bundle/config new file mode 100644 index 0000000..848943b --- /dev/null +++ b/agent-mobile/artimobile/.bundle/config @@ -0,0 +1,2 @@ +BUNDLE_PATH: "vendor/bundle" +BUNDLE_FORCE_RUBY_PLATFORM: 1 diff --git a/agent-mobile/artimobile/.eslintrc.js b/agent-mobile/artimobile/.eslintrc.js new file mode 100644 index 0000000..187894b --- /dev/null +++ b/agent-mobile/artimobile/.eslintrc.js @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: '@react-native', +}; diff --git a/agent-mobile/artimobile/.gitignore b/agent-mobile/artimobile/.gitignore new file mode 100644 index 0000000..0cab2ac --- /dev/null +++ b/agent-mobile/artimobile/.gitignore @@ -0,0 +1,66 @@ +# OSX +# +.DS_Store + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate +ios/.xcode.env.local + +# Android/IntelliJ +# +build/ +.idea +.gradle +local.properties +*.iml +*.hprof +.cxx/ +*.keystore +!debug.keystore + +# node.js +# +node_modules/ +npm-debug.log +yarn-error.log + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/ + +**/fastlane/report.xml +**/fastlane/Preview.html +**/fastlane/screenshots +**/fastlane/test_output + +# Bundle artifact +*.jsbundle + +# Ruby / CocoaPods +/ios/Pods/ +/vendor/bundle/ + +# Temporary files created by Metro to check the health of the file watcher +.metro-health-check* + +# testing +/coverage diff --git a/agent-mobile/artimobile/.prettierrc.js b/agent-mobile/artimobile/.prettierrc.js new file mode 100644 index 0000000..2b54074 --- /dev/null +++ b/agent-mobile/artimobile/.prettierrc.js @@ -0,0 +1,7 @@ +module.exports = { + arrowParens: 'avoid', + bracketSameLine: true, + bracketSpacing: false, + singleQuote: true, + trailingComma: 'all', +}; diff --git a/agent-mobile/artimobile/.watchmanconfig b/agent-mobile/artimobile/.watchmanconfig new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/agent-mobile/artimobile/.watchmanconfig @@ -0,0 +1 @@ +{} diff --git a/agent-mobile/artimobile/App.tsx b/agent-mobile/artimobile/App.tsx new file mode 100644 index 0000000..125fe1b --- /dev/null +++ b/agent-mobile/artimobile/App.tsx @@ -0,0 +1,118 @@ +/** + * Sample React Native App + * https://github.com/facebook/react-native + * + * @format + */ + +import React from 'react'; +import type {PropsWithChildren} from 'react'; +import { + SafeAreaView, + ScrollView, + StatusBar, + StyleSheet, + Text, + useColorScheme, + View, +} from 'react-native'; + +import { + Colors, + DebugInstructions, + Header, + LearnMoreLinks, + ReloadInstructions, +} from 'react-native/Libraries/NewAppScreen'; + +type SectionProps = PropsWithChildren<{ + title: string; +}>; + +function Section({children, title}: SectionProps): React.JSX.Element { + const isDarkMode = useColorScheme() === 'dark'; + return ( + + + {title} + + + {children} + + + ); +} + +function App(): React.JSX.Element { + const isDarkMode = useColorScheme() === 'dark'; + + const backgroundStyle = { + backgroundColor: isDarkMode ? Colors.darker : Colors.lighter, + }; + + return ( + + + +
+ +
+ Edit App.tsx to change this + screen and then come back to see your edits. +
+
+ +
+
+ +
+
+ Read the docs to discover what to do next: +
+ +
+ + + ); +} + +const styles = StyleSheet.create({ + sectionContainer: { + marginTop: 32, + paddingHorizontal: 24, + }, + sectionTitle: { + fontSize: 24, + fontWeight: '600', + }, + sectionDescription: { + marginTop: 8, + fontSize: 18, + fontWeight: '400', + }, + highlight: { + fontWeight: '700', + }, +}); + +export default App; diff --git a/agent-mobile/artimobile/Gemfile b/agent-mobile/artimobile/Gemfile new file mode 100644 index 0000000..8d72c37 --- /dev/null +++ b/agent-mobile/artimobile/Gemfile @@ -0,0 +1,9 @@ +source 'https://rubygems.org' + +# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version +ruby ">= 2.6.10" + +# Cocoapods 1.15 introduced a bug which break the build. We will remove the upper +# bound in the template on Cocoapods with next React Native release. +gem 'cocoapods', '>= 1.13', '< 1.15' +gem 'activesupport', '>= 6.1.7.5', '< 7.1.0' diff --git a/agent-mobile/artimobile/README.md b/agent-mobile/artimobile/README.md new file mode 100644 index 0000000..12470c3 --- /dev/null +++ b/agent-mobile/artimobile/README.md @@ -0,0 +1,79 @@ +This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli). + +# Getting Started + +>**Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding. + +## Step 1: Start the Metro Server + +First, you will need to start **Metro**, the JavaScript _bundler_ that ships _with_ React Native. + +To start Metro, run the following command from the _root_ of your React Native project: + +```bash +# using npm +npm start + +# OR using Yarn +yarn start +``` + +## Step 2: Start your Application + +Let Metro Bundler run in its _own_ terminal. Open a _new_ terminal from the _root_ of your React Native project. Run the following command to start your _Android_ or _iOS_ app: + +### For Android + +```bash +# using npm +npm run android + +# OR using Yarn +yarn android +``` + +### For iOS + +```bash +# using npm +npm run ios + +# OR using Yarn +yarn ios +``` + +If everything is set up _correctly_, you should see your new app running in your _Android Emulator_ or _iOS Simulator_ shortly provided you have set up your emulator/simulator correctly. + +This is one way to run your app — you can also run it directly from within Android Studio and Xcode respectively. + +## Step 3: Modifying your App + +Now that you have successfully run the app, let's modify it. + +1. Open `App.tsx` in your text editor of choice and edit some lines. +2. For **Android**: Press the R key twice or select **"Reload"** from the **Developer Menu** (Ctrl + M (on Window and Linux) or Cmd ⌘ + M (on macOS)) to see your changes! + + For **iOS**: Hit Cmd ⌘ + R in your iOS Simulator to reload the app and see your changes! + +## Congratulations! :tada: + +You've successfully run and modified your React Native App. :partying_face: + +### Now what? + +- If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps). +- If you're curious to learn more about React Native, check out the [Introduction to React Native](https://reactnative.dev/docs/getting-started). + +# Troubleshooting + +If you can't get this to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page. + +# Learn More + +To learn more about React Native, take a look at the following resources: + +- [React Native Website](https://reactnative.dev) - learn more about React Native. +- [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup your environment. +- [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**. +- [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts. +- [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native. diff --git a/agent-mobile/artimobile/__tests__/App.test.tsx b/agent-mobile/artimobile/__tests__/App.test.tsx new file mode 100644 index 0000000..9eac6fb --- /dev/null +++ b/agent-mobile/artimobile/__tests__/App.test.tsx @@ -0,0 +1,17 @@ +/** + * @format + */ + +import 'react-native'; +import React from 'react'; +import App from '../App'; + +// Note: import explicitly to use the types shipped with jest. +import {it} from '@jest/globals'; + +// Note: test renderer must be required after react-native. +import renderer from 'react-test-renderer'; + +it('renders correctly', () => { + renderer.create(); +}); diff --git a/agent-mobile/artimobile/android/app/build.gradle b/agent-mobile/artimobile/android/app/build.gradle new file mode 100644 index 0000000..01cb18a --- /dev/null +++ b/agent-mobile/artimobile/android/app/build.gradle @@ -0,0 +1,119 @@ +apply plugin: "com.android.application" +apply plugin: "org.jetbrains.kotlin.android" +apply plugin: "com.facebook.react" + +/** + * This is the configuration block to customize your React Native Android app. + * By default you don't need to apply any configuration, just uncomment the lines you need. + */ +react { + /* Folders */ + // The root of your project, i.e. where "package.json" lives. Default is '..' + // root = file("../") + // The folder where the react-native NPM package is. Default is ../node_modules/react-native + // reactNativeDir = file("../node_modules/react-native") + // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen + // codegenDir = file("../node_modules/@react-native/codegen") + // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js + // cliFile = file("../node_modules/react-native/cli.js") + + /* Variants */ + // The list of variants to that are debuggable. For those we're going to + // skip the bundling of the JS bundle and the assets. By default is just 'debug'. + // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. + // debuggableVariants = ["liteDebug", "prodDebug"] + + /* Bundling */ + // A list containing the node command and its flags. Default is just 'node'. + // nodeExecutableAndArgs = ["node"] + // + // The command to run when bundling. By default is 'bundle' + // bundleCommand = "ram-bundle" + // + // The path to the CLI configuration file. Default is empty. + // bundleConfig = file(../rn-cli.config.js) + // + // The name of the generated asset file containing your JS bundle + // bundleAssetName = "MyApplication.android.bundle" + // + // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' + // entryFile = file("../js/MyApplication.android.js") + // + // A list of extra flags to pass to the 'bundle' commands. + // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle + // extraPackagerArgs = [] + + /* Hermes Commands */ + // The hermes compiler command to run. By default it is 'hermesc' + // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" + // + // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" + // hermesFlags = ["-O", "-output-source-map"] +} + +/** + * Set this to true to Run Proguard on Release builds to minify the Java bytecode. + */ +def enableProguardInReleaseBuilds = false + +/** + * The preferred build flavor of JavaScriptCore (JSC) + * + * For example, to use the international variant, you can use: + * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` + * + * The international variant includes ICU i18n library and necessary data + * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that + * give correct results when using with locales other than en-US. Note that + * this variant is about 6MiB larger per architecture than default. + */ +def jscFlavor = 'org.webkit:android-jsc:+' + +android { + ndkVersion rootProject.ext.ndkVersion + buildToolsVersion rootProject.ext.buildToolsVersion + compileSdk rootProject.ext.compileSdkVersion + + namespace "com.artimobile" + defaultConfig { + applicationId "com.artimobile" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 1 + versionName "1.0" + } + signingConfigs { + debug { + storeFile file('debug.keystore') + storePassword 'android' + keyAlias 'androiddebugkey' + keyPassword 'android' + } + } + buildTypes { + debug { + signingConfig signingConfigs.debug + } + release { + // Caution! In production, you need to generate your own keystore file. + // see https://reactnative.dev/docs/signed-apk-android. + signingConfig signingConfigs.debug + minifyEnabled enableProguardInReleaseBuilds + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + } + } +} + +dependencies { + // The version of react-native is set by the React Native Gradle Plugin + implementation("com.facebook.react:react-android") + implementation("com.facebook.react:flipper-integration") + + if (hermesEnabled.toBoolean()) { + implementation("com.facebook.react:hermes-android") + } else { + implementation jscFlavor + } +} + +apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) diff --git a/agent-mobile/artimobile/android/app/debug.keystore b/agent-mobile/artimobile/android/app/debug.keystore new file mode 100644 index 0000000000000000000000000000000000000000..364e105ed39fbfd62001429a68140672b06ec0de GIT binary patch literal 2257 zcmchYXEfYt8;7T1^dLH$VOTZ%2NOdOH5j5LYLtZ0q7x-V8_6gU5)#7dkq{HTmsfNq zB3ZqcAxeY^G10@?efK?Q&)M(qInVv!xjx+IKEL}p*K@LYvIzo#AZG>st5|P)KF1_Z;y){W{<7K{nl!CPuE z_^(!C(Ol0n8 zK13*rzAtW>(wULKPRYLd7G18F8#1P`V*9`(Poj26eOXYyBVZPno~Cvvhx7vPjAuZo zF?VD!zB~QG(!zbw#qsxT8%BSpqMZ4f70ZPn-3y$L8{EVbbN9$H`B&Z1quk9tgp5FM zuxp3pJ0b8u|3+#5bkJ4SRnCF2l7#DyLYXYY8*?OuAwK4E6J{0N=O3QNVzQ$L#FKkR zi-c@&!nDvezOV$i$Lr}iF$XEcwnybQ6WZrMKuw8gCL^U#D;q3t&HpTbqyD%vG=TeDlzCT~MXUPC|Leb-Uk+ z=vnMd(|>ld?Fh>V8poP;q;;nc@en$|rnP0ytzD&fFkCeUE^kG9Kx4wUh!!rpjwKDP zyw_e|a^x_w3E zP}}@$g>*LLJ4i0`Gx)qltL}@;mDv}D*xR^oeWcWdPkW@Uu)B^X&4W1$p6}ze!zudJ zyiLg@uggoMIArBr*27EZV7djDg@W1MaL+rcZ-lrANJQ%%>u8)ZMWU@R2qtnmG(acP z0d_^!t>}5W zpT`*2NR+0+SpTHb+6Js4b;%LJB;B_-ChhnU5py}iJtku*hm5F0!iql8Hrpcy1aYbT z1*dKC5ua6pMX@@iONI?Hpr%h;&YaXp9n!ND7-=a%BD7v&g zOO41M6EbE24mJ#S$Ui0-brR5ML%@|ndz^)YLMMV1atna{Fw<;TF@>d&F|!Z>8eg>>hkFrV)W+uv=`^F9^e zzzM2*oOjT9%gLoub%(R57p-`TXFe#oh1_{&N-YN z<}artH|m=d8TQuKSWE)Z%puU|g|^^NFwC#N=@dPhasyYjoy(fdEVfKR@cXKHZV-`06HsP`|Ftx;8(YD$fFXumLWbGnu$GMqRncXYY9mwz9$ap zQtfZB^_BeNYITh^hA7+(XNFox5WMeG_LtJ%*Q}$8VKDI_p8^pqX)}NMb`0e|wgF7D zuQACY_Ua<1ri{;Jwt@_1sW9zzdgnyh_O#8y+C;LcZq6=4e^cs6KvmK@$vVpKFGbQ= z$)Eux5C|Fx;Gtmv9^#Y-g@7Rt7*eLp5n!gJmn7&B_L$G?NCN`AP>cXQEz}%F%K;vUs{+l4Q{}eWW;ATe2 zqvXzxoIDy(u;F2q1JH7Sf;{jy_j})F+cKlIOmNfjBGHoG^CN zM|Ho&&X|L-36f}Q-obEACz`sI%2f&k>z5c$2TyTSj~vmO)BW~+N^kt`Jt@R|s!){H ze1_eCrlNaPkJQhL$WG&iRvF*YG=gXd1IyYQ9ew|iYn7r~g!wOnw;@n42>enAxBv*A zEmV*N#sxdicyNM=A4|yaOC5MByts}s_Hpfj|y<6G=o=!3S@eIFKDdpR7|FY>L&Wat&oW&cm&X~ z5Bt>Fcq(fgnvlvLSYg&o6>&fY`ODg4`V^lWWD=%oJ#Kbad2u~! zLECFS*??>|vDsNR&pH=Ze0Eo`sC_G`OjoEKVHY|wmwlX&(XBE<@sx3Hd^gtd-fNwUHsylg06p`U2y_={u}Bc + + + + diff --git a/agent-mobile/artimobile/android/app/src/main/AndroidManifest.xml b/agent-mobile/artimobile/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..4122f36 --- /dev/null +++ b/agent-mobile/artimobile/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + diff --git a/agent-mobile/artimobile/android/app/src/main/java/com/artimobile/MainActivity.kt b/agent-mobile/artimobile/android/app/src/main/java/com/artimobile/MainActivity.kt new file mode 100644 index 0000000..202b285 --- /dev/null +++ b/agent-mobile/artimobile/android/app/src/main/java/com/artimobile/MainActivity.kt @@ -0,0 +1,22 @@ +package com.artimobile + +import com.facebook.react.ReactActivity +import com.facebook.react.ReactActivityDelegate +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled +import com.facebook.react.defaults.DefaultReactActivityDelegate + +class MainActivity : ReactActivity() { + + /** + * Returns the name of the main component registered from JavaScript. This is used to schedule + * rendering of the component. + */ + override fun getMainComponentName(): String = "artimobile" + + /** + * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] + * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] + */ + override fun createReactActivityDelegate(): ReactActivityDelegate = + DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) +} diff --git a/agent-mobile/artimobile/android/app/src/main/java/com/artimobile/MainApplication.kt b/agent-mobile/artimobile/android/app/src/main/java/com/artimobile/MainApplication.kt new file mode 100644 index 0000000..a6a5121 --- /dev/null +++ b/agent-mobile/artimobile/android/app/src/main/java/com/artimobile/MainApplication.kt @@ -0,0 +1,45 @@ +package com.artimobile + +import android.app.Application +import com.facebook.react.PackageList +import com.facebook.react.ReactApplication +import com.facebook.react.ReactHost +import com.facebook.react.ReactNativeHost +import com.facebook.react.ReactPackage +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load +import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost +import com.facebook.react.defaults.DefaultReactNativeHost +import com.facebook.react.flipper.ReactNativeFlipper +import com.facebook.soloader.SoLoader + +class MainApplication : Application(), ReactApplication { + + override val reactNativeHost: ReactNativeHost = + object : DefaultReactNativeHost(this) { + override fun getPackages(): List = + PackageList(this).packages.apply { + // Packages that cannot be autolinked yet can be added manually here, for example: + // add(MyReactNativePackage()) + } + + override fun getJSMainModuleName(): String = "index" + + override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG + + override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED + } + + override val reactHost: ReactHost + get() = getDefaultReactHost(this.applicationContext, reactNativeHost) + + override fun onCreate() { + super.onCreate() + SoLoader.init(this, false) + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + // If you opted-in for the New Architecture, we load the native entry point for this app. + load() + } + ReactNativeFlipper.initializeFlipper(this, reactNativeHost.reactInstanceManager) + } +} diff --git a/agent-mobile/artimobile/android/app/src/main/res/drawable/rn_edit_text_material.xml b/agent-mobile/artimobile/android/app/src/main/res/drawable/rn_edit_text_material.xml new file mode 100644 index 0000000..73b37e4 --- /dev/null +++ b/agent-mobile/artimobile/android/app/src/main/res/drawable/rn_edit_text_material.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + diff --git a/agent-mobile/artimobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/agent-mobile/artimobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..a2f5908281d070150700378b64a84c7db1f97aa1 GIT binary patch literal 3056 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 axPAxe%7rDusX+w*00006jj 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⁣ zwiG+x#%j}{0gU~J8;<|!B1@-XaB@{KORFwrYg_8rOv({b0EO#DbeQRm;B6_9=mXGf z-x|VL{zd`)#@yN}HkCSJbjbNlE|zL3Wm9Q8HY`sV)}3%pgN>cL^67{Z;PPL(*wT8N zUjXU{@|*hvm}({wsAC=x0^ok0%UAz0;sogW{B!nDqk|JJ5x~4NfTDgP49^zeu`csl?5mY@JdQdISc zFs!E{^grmkLnUk9 zny~m)1vws@5BFI<-0Tuo2JWX(0v`W|t(wg;s--L47WTvTMz-8l#TL^=OJNRS2?_Qj z3AKT+gvbyBi#H*-tJ%tWD|>EV3wy|8qxfzS!5RW;Jpl5*zo&^UBU=fG#2}UvRyNkK zA06Dy9;K1ca@r2T>yThYgI!ont$(G{6q#2QT+00r_x0(b)gsE`lBB?2gr55gq^D3Fi&p%E(p9>U%bv zkg1Jco(RbyTX7FDHOnl7-O@ zI$AaIl?9NJKPm(WiBP`1-#CB1QzU>&hKm)fpa5DKE{2$X0hGz-0uZ?cyTk(YC!Y&| zL=1VrNERSA5NA2jq7FACfX4JfPyj5XXl1yv0>~s;eF7L2$>&oMqeTFT2m$y7FlkON z_yurD1yIOvA;5C6016pyxBznGUt0kJ&k5r#;&>Jow`r)sp9R~PmK~lz$3xH%LT*1U zJdOyABZ3!FvNoR*vN$5ykHS8f`jA4zV+|L}i1C4`B2c{R0;UdYxaU|H)2avz@ z=mEYc|2S<+(B2Tj+FkX+2D+yFI!k9lWMA61DJ{)e;lum$(;O87?vGJJe!KtK04+N_ zI*P~t@dUb>9Xh{dbyl{-ZQ(UMgz7$|QfL5XSPkskt^NgctYC#;4WcZB1@%@wy@2t3 z2z0DI7&%b$*Aw~abe?GxE`ez@+6hOh-6*8fHRV{1os$EL@}uUZeG4h1&Be`98q*7j z=3-v+lhIjfWVo12!<>%V^a6lTgW3+_#W6n|p*~==zOH7z$0{LSZk(Tpd7EaD04hnA zL;#fxS0aD{`5^&D`}>0Uq?byDD-l2=!wm_bLcUl4gc(% za1p|itVANvFF>hghAS07Im1;IK;|b*W)}VDyI;BIp2=K*yu2a)j?B|f<44NI$NbmJ z#dE0>jI$fMr&@>4kN8MLFb4&2O9fEKaQg%(QO$4_1rVQywG^CmBLh#}_7gKW3vd?| z2?1^&KWq8}8I^_S0|)MowU_pw$q@nl@Nkn$z>BQq_KA^9yaR`(R3u{{Ig;cwt z@AJ^{ODQCm^neroM9nKNUAXi9RCK`OsP_LuR0PUR(YZCCX5dNF6VzcoK&=b^r`W?ltt|*F zpkoae%ZT{C1h~EcFui~b7fF`vb<<~j_VquuUA$}QqIKYELPp#;{u?q8Dz}WAG-(3; zjrm$i%7UbyZMM(Y{>!uJ#vNB?R~B{6Htp=>e*<{fQQ5W7V(1coCWlOON!MzZxhum| ztZBQpGR z;~#ur^&PockKdV{Q6R>o`Pl{0x!DEbpZ7y9Y;*ZvE!*gU`V1W3znva{f=?WO5I&>B z&hw6}tjECtaghm5z|C#%M;Yf_*pI^};h}Vl=^r9EN=tVDj86D;C$jIJ?K7VP+00000NkvXXu0mjf D5i!M* literal 0 HcmV?d00001 diff --git a/agent-mobile/artimobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/agent-mobile/artimobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..459ca609d3ae0d3943ab44cdc27feef9256dc6d7 GIT binary patch literal 7098 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 literal 0 HcmV?d00001 diff --git a/agent-mobile/artimobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/agent-mobile/artimobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..8ca12fe024be86e868d14e91120a6902f8e88ac6 GIT binary patch literal 6464 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 B0*L?s literal 0 HcmV?d00001 diff --git a/agent-mobile/artimobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/agent-mobile/artimobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..8e19b410a1b15ff180f3dacac19395fe3046cdec GIT binary patch literal 10676 zcmV;lDNELgP)um}xpNhCM7m0FQ}4}N1loz9~lvx)@N$zJd<6*u{W9aHJztU)8d8y;?3WdPz&A7QJeFUv+{E$_OFb457DPov zKYK{O^DFs{ApSuA{FLNz6?vik@>8e5x#1eBfU?k4&SP;lt`%BTxnkw{sDSls^$yvr#7NA*&s?gZVd_>Rv*NEb*6Zkcn zTpQm5+>7kJN$=MTQ_~#;5b!%>j&UU=HX-HtFNaj*ZO3v3%R?+kD&@Hn5iL5pzkc<} z!}Vjz^MoN~xma>UAg`3?HmDQH_r$-+6~29-ynfB8BlXkvm55}{k7TadH<~V$bhW)OZXK@1)CrIKcRnSY`tG*oX}4YC&HgKz~^u7 zD?#%P?L~p~dt3#y(89y}P;ij|-Z#KC;98PvlJCjf6TQbsznsL8#78n~B_kaQl}nsm zLHr7z%-FAGd=-!e?C{q62x5i4g4hNuh)LeqTa4ynfC4h(k*e>okrBlLv;YG%yf8!6 zcN)a^5>rp^4L+myO70z(0m`D}$C(eqfV1GpzM+%$6s6$?xF>~%Gzx|$BUZ$=;f)B8 zoQUrc!zB4kT!wqSvJ=ywY-W)3364w!`U>J+49ZE`H~+{!gaM)zFV!?!H+)k8BnOj3 zGvU93auN}g?X^8c`+PFv|EH=R%m)iUN7gssWyTD~uv7prl1iRfRaCFeJUuA@$(p&K z?D+cmhxf`n9B~!?S#d*TeLb^(q~VYS$3KhjfwfMWtZx&PlTZ(i@5HJ?of_Q)0YX99 z35b?W>?=vlb6gtK1ydcF4<@aH|Hgj8r?~QNOPx(YoKT^Xn=?Q%=1uA&-G(}mXdtsT zQuKACS|@G@uBW(SY(cH%% zq+xr%bpGqOGHyw3=8K7;J&hp^g1UsyG zYT24BGeGQukP?&TlOBE2H$2oH>U#E>GtI-fmc)17uc`7FRxJ3A!c%ADN^Z^oi6tYp zjzE+a{r&jt6z^scbd(feWPVEE!lV1I4lfdLhQ|yLdx&1IEV%l1erB&H8X}3=8lIcc zCNPUis-KRbCC z20@WYl&vVEZo!fLXxXs?{|<|Z=>0^-iX;y6{DT$lSo8b|@FZM3U$+W37(A_9<)fnq zP~11?(AKlHI-Lh(`?-@S?(1{t16bc7ESX->9twFP@t8_XK$XxuSFF#R(g7H(U%XvWa zm}J>%4-suYL=gX7-_MsjD27o?I!G888fxV$koLCfOv+Da&OVTG*@(aC9lz_e>*UGS zrX6f-45hd55ya-p_O{FbHEG%Ee9~i(H-B3RZkv`0ZDn$!>MigMZX06&y3RSk-WnL-{cM1 z1TZr|rc*Xaf|_^y&YLc4KK3<@aWfge2jARbRRg1DfJ~%pV9L_@$UADw3EXC_n%p0v zQO*{=88K@W{T?$wCR#S!M!e+R$aDL~EzovN7pbOBvrk&&ASS=Z43No|jrc>}aXXO5 zrd1<|Qypq-h#J*iORN@8YRc&`17u=lqo&L&YV%p#hL%P*WfIfH%ZUC^o#`?IWWr?w zQ^?EgP7!lqlq}ZM}d*sSVz(mqeQrA_huV@M4iwXa>k+%O-ZHW44JrRxLJy zLoHTuEqw(sMcO38n*lQ6ve97<&+Y50NNmVpW{hed@5EgrWfI~ITFJ0D(<|k)ag-~cV z0@-#S9z8&EUfBL7C_53YJ$)2ix^)vhsH;Q&KDdwe{q{2oJ#~b@#Qr?YGHrh;`rz<> z)F&rNr}J@}p8^N(8hLRH`=jpeT@y z2v7WETpnG{qixxkWWyK7(3QJ)RF-$=`O^k3+oY;O;rNnl^kVc*(j(Jb_99(Dw1w;T z4K8fsKDzn|epoWT|5{~*3bCC1>nd5;@=5lApq%3>^U_gQD>5j-O@WH;uEG+4MSBjJkdgtP;JG2`S&&Sa#_w33(yyAux~lnp7>wMXzD4yy_2#Vh+7&WMkWFl9Ohq06ifTiMWIC(|1Fe(3n}U_0(+jGC_(1c@X4vzk6y`)qzH+WXtj>dhI3=)~1Oi0Omh z^vp^i61ge1rO8;F~ncj_=tk zIvnwqFB-?)jER5LdQ?Hi=Kv5dgPZx%XSjc8VLCd4yYK4E88pIi4AGWzwdmrFf6&AF zI-`N3cpnf!Klj%)afJEC-x{^po?kDKD0@>6(}1f2xkCOMS49E?+5^EenLUrqK%EANgiQdAy8BW0e}Fvw`>)CTcvBeX6ZgjWC~(KdFE9hv+M6*t z?loxF7N3yv+}r*v(>9DX;0V1TP3G)L5r}m~e)RO*pc zv#tyehrK*U7ilRPA zk!aAmm9v3`z|hH7+WJ41!*h~g<2G1sUubFoL9b?dbp>%)pHzUZ-n)Z)W(6jh>jY-3 zUq&n%9=y?`ajN7rr3`t68sL^H^MG_rUDQw2$gj4Jb8MXgAW99^EbKmu9*Pv4Rh3=;vUVF30sUrdj!_n0*+m?WCbo^8q2fo|;?vH3OFh4__< zyaqNQdP4&Q+6R)%gv|^b#b|oW*XMMKLhEgy7(3D!poW*Tk`Qn4f*HUBD@U4+eOL|4 zh+hT+hl`Hx6+v(dZi=hGf|lF9JV};bs&Bm{THmunMOu))>8UdnTYV%TFdKB!dzN+?+5S+WYI><_z_6eDC z+WvMv78tB-j%G_;_de;{^Q7!t>Khj7gp^izaCK?7PmUiHevBXbk=s8{114AjWHDj{ z_(0ZvDUl`5mu8_cWw}Ba6$W+4RbZ4H97I^qQrq9Yd$5A!1wSqDNaUXf_sQ%GF7*wX zXFhfrz!d7zZiDhtgk#HcP(aukNVacB**=V7u3*Xwp&aR_R8vnbd1PGG6$}j(F_VMA?KUK~Jd?J)TjC!h3~KL|i&IYtL40AFtv zb_DC5Vt8aT6JhF5fEI0_FM#^zCX2>a=A#}FVOKjnH_(#+q}Ggy0kU*_?=3Ifjr+H$ z0D{~ZO<8+Sll*k^U-Y6DvsCpBP|v8XH*H@U(US~mumH%)dBJRde1f|G&@1J+MvVi( zla}?vMV%}C?xRQOryKvG8`v3bs)mPaL*v7}=z1;z?uq)tAg6HwY9Ihbhu^awAJU&S zK#m{H4)PVmJ!}eqpy%MRP$Pe(&D;?N7($!Oz=8uTxRyl1Wg*V=gE z5PBge1q~I%qmY6Ol#1^O?u~P=44?CDh*GEXjSmoi`y;!_V+I2o>H!jms@u4HII9l^ z=&`W@f)v#1KQ8O!bY@+=fC3VBA@A7jQt^q~fz}*7i0(grY=jujW3=vAHS&qyN!B3* z;l=MjJrW~O7Sz5xp2Z?EtA`naLM239gw8Ub=%IHPY<00fb5 zozf%j+(s|urpUn~5r5pE7yi0taDcx4`#K81u*kwAk(cvQ$vx_F{wd}8h=eKDCE$M(iD9_QGJh zr0e(Z>QuRZ+`ff^GZPu%;bA#_^$&vsboSa6V!jmN0SV4dBKN4v`C)aESBtZV7J~U( zOc3e47Zx3Ux67y(o?#7;!=y1jxEueEF#$^c_PoxG_pq)GZLU2`d>%!3rdJjkrAK!2 z!2>jNPceo_9v)xpmu)_EgxsU9*GT^QoERVik+LSzH$Z{Ax7_GFY+!HA0MSfDyXT(k z?vob%yRiU**{7No8PKK&w77Z?8j#9IJ#hv1O^!lS%kt0n7@x79#}+R-TuINbiBfotv)O^y=kD0AkUNhrP$U_@qXE zYpkIR$Zgi=#6Os0^$m7rt1kV3&R~;r&xn%>8xzDHk!yob^vyrl^*R$4R_u5eYdHc> zk}^bkAIjLe{t{-Q8+D@9&dz9Q;o$+RGT7l8sx<~c5IBs*Dp_bAwqQRM2olfEe}Vk4 zc9Vt3hx$Z%0|;xNF=aW(Z*%CEmg_ z-riR#1Wjb9t+D^_K$%|E`_m#&XHzQ*&~vzFCzYIJB6Ieap%urgb=%UsC<9^hC4{(B z(3+*N>|JNdhT54KE$HT~okqq-teADE3Vn9^sA!>%+fb|98XIO zePvP!J8>9Ao~cC(u@>UqZhO(v+C!ob_m!fdtCwsACbR*lqtAwwQ@{hCy1%pm)*>|2 z*4U}vUNFO;Lw9~?Rw9)osm$D4f)?XmUvN$e8eWjjsm+Gr-@$~6iMgqWH+%YAV1gAu z7NbW)FU+RvtZ75ADtlW83vAW@YkP-BMr{8tV}A+L9?({@=u8(K9O&F z4CiS*&nHDa>J}36GR;VAs~I41Kfit308jVeg0#zIVj;(cr8EHqE6<OP0C9kbOl`)daY)$O<0J;;?A%Ve z&#H!_rNfB84*1o6aD2oLL(Ywd^#ZTmyK9Dlqg=at2TjDGCcH@qymjUqbf4FvGxc*ap|#6x@}Ug@+NK z6j_PV43T(wmxf+(J5kT~r++|VKw>6X0o1~R#{);Yll!>QeP1cfzTvOK0-Ndpf;nGz znqZirxrk&)Llzz-fKnnEL_I{Lt#O<8-0}IX?!m#sfdv{wY{3p7aF*=sI^w@wUdl;1 zOaQ`8mA(OjeI_2&*O_79989c3v-g+F!6OGyYBVD}5>W|JMvMsd5c6BV0+zUQBP_6V zpc@@&KR+A%>NFy5N0^}idafWHEjUnt=I<|KC5!NPqrW(T!j9Ll{*5Zxa^f&K*Ftjr zawS=CfJrKpWc85)DE8bbv=YBAz#5gkRLaSR_+g6q@-*6f>L^-JT`4CEtE*JX@Z1zF z0E&{AR0fE|??ogjZqfU3(3!I1@j9|~pd0<5UcI0vX5Z_hd1HMA@j|Yv)N2|G^GS;q zXYi@WB9s-#b)He4kH+MtvHHF`8K0kl-oxkemC0RJl}RX;os2R(GXc%6Dn>&D@rZ}- zPb!J(Btl-2B2W+9n6vkmpjV4Bl?F&viUK%NfXXmH_#u%8D2iDWAcFW0m@khVp9{N9 z7&DbP(1Gk7XhlD$GZqiugk2XTu>nJ*bAY;J1CcQR(gq#?Wq4+yGC*3wqY5A{@Bl2z z0I7yYB2tLJe5Lb|+h?DCkK5jdFd$~3g?0d0ShVgG6l4p2kXQKH?S=$M3{jLui1Y>! zz77*W+QP#K5C?de0OAUdGC-Q)A%ZOd%_kz}%W2+>L}>etfq`~pMyi$o5kJUY><4vq zdT;7z-}KnW2H$K&gE`X+Kok~5fVjY;1Q17f6amr&9##OQG7B#?nzXIwwheWiM!)a| zv^^L9r_m3B3^W^?E?~yI`Qf!(wU9Ow3)Pu3odJ?DRk8qag@-*r>fw?ty;X?M?5GeGW6VdRS@X}kbfC>Ph0tSHC!=o7> zcJP1%;)e#h-i!cg0S|z}2#|Ws1LjKvukP!X{cY{zF$mh+!rtD7tND^MV;y)-ur`c4 zFKkU>&&+tOw*1y*YwVu5X8==z0UVItNs(wyMIoAiwTI+0%@V;VuNP&ZIh92y2&-(k zMi0;exUrZe67@)CmgjR)(0ttRFy~A9c}gUif~+K|%mVQAO^-$M_Lq|w4!my^J_<}z zA?b<|Lu5*2A)0rv67|lAMLqF*s7KWjivr(f4{^A5$f4qjg zmxyepp;Y!W2-Y|f2|IZNMV_rib8+3xIZ#3BP@Ul4G|a88M6V}A)%k~vnh0%eYirwy zYwt@rDs5q5-M(vANBrvba>DMCi52-;ZT+q5*4X2*N*nu4*&?uY&0IEM1_>fN{*6zdU!wDfFIgPxZWn<9+^rhhu0i5u{>8eHa7)5yJ`s} z&wJ6fw${~r$vM*&uCCxryLOp0cDzs0u6k{{^!ivQ8f-O~8dg3KgU_SbRiA)C08Qiv zzKj+=kD{M5JWJLGV(;@P`ZkfJkBl^sz+u>GVaJz7K;+rg z!o@{r=UEY;R%DelCy0#G3URLBevOL)`* zqy;>(0F74#5KDMKCSwZ$ri&3ES$H7!lg1Z%!6v&4XYGNurEM%p9@7gz5@*`VqGLzU zLT+15_Xc^?TikPBx22wj=^SZ zs}Z0G&hW4Wh|SoR5uCl&CJhu&k`der5ui5sCU4Xu6TeIXd)x3=z%U;RBc ztv*7s+cIP7jSY}0h}ev6NdZcX;0%u}Krp$FD?Ca7=>U&BKrt%d;n#!acKLYTY21bZ zv@JUu!uL_#BXe+Yf|!Brh+$)}DSJRnnTjC}Ljoio_TWn)VmmNO0IF00kQSrrFee?R z7Bc~)&8WJ1fTFY-RVM%)WCnDP(H}A& zhBl&Y)kS8&w1q_z9gU_85|G-ofg9`TvUE|dcg!}aDQgOV5Q)DNUCuQ)WYLDoh0la$WgJ4Rotv zl73SGB!!5ft4;u_0)Tewlu1aIlv4$e7NhEr2*wDImhcdODhmiee(7;S&)u7m^TJuj zaGUfdZDVciLfWbcO&60EYDq)jov~-{4mK7`pYEYc&w@icvLv$}mP~63fQaCyo2Ss* zQVo!HDH$pO(lRB35g-omfawMe^nP_^y$^poa`|Z9SFjm3X%lhVbe0*eXklR@hpazj z*S1q9FNjjxxVQ}d->$7c!mNdD=TFtot*O#!`|xS|OHuf_lO(fI+uy#9pUO$a*#sOA z$Rylwv>Hv8d{!)xY^h8tQ6spaLFVi$MVo35lV#;3pFwgMqm(I19?9JSfizUeB!pxz zcn=V0Ex3&Ey6Qwt{o0znXyk^^eztLT9tLee+r-Wk{2opI5JWWXJ32UktqpML9XRs6 z#MobUojQtE)E=tWWgF@baOJ{w)?sH(aQZ!{b=ZagG!MYD6E_&Z4eyD-|6~MGQ5j`# z30VOQ`vMH%@f}La~!CD6da+o0vbz|)znwna{EC?cc;6-Qy+!o+g*weOYZHn;7XD^B!GzUq~%s$X>)e$w?x< z)Z{%y9JjKLLjf7F$S-*}(L4YTB*B9jlapkLL@J3tktnH*$W0;n%wWo3O+r{wMM+Xs z312FZ01r9LkcJA*uaczmNv}$!;O~IX;}g9Njo7gI5`{<7<8q*FVrk0oC=PXy=|H#u zKz|QgXXl|oYge50=7$rDoC!A zwmuJZ)k$wFA`CfyIQN20w{F8JJU+C?)xnrU75an-ynV+u_V&K`HPF)1vY*SRA5?qo z4wJ-*MB1#|r!Rm&z+V6}B?l0Pe4bzc2%Dl|*~vO(62cT4m?6OkkScgmqa{JY29NC< zP`3p$kKj5U0CjC6u5(A)29~DgG_&oQS$!%!~kOnUbLrAa(Fytpgg!eRC*soc&G_uG_vu^N8!(Nuj&` z#K5BpB1am;3cv;J?KETBHutTeLYRx~!*UT%eFH@HlYnR~Xd#ZtV2l89$md}MNCP~) z#NEhk{c@q>)Yl@QPDyT$xQ-p4baOh=17y<6kArSxF%WmxdX1ad1CA`8-MhaZCnN0!T$BAvIYd$Ypk2y6B4Si@|dVJW!`?+j>!lxq~SM z3ias|wWr-lH!C{=QINH>!!YMh<{ktaPS&W&jIB2|K;l(L3bab7U{MCX3JClZr|>x|SL)ShO73*>(Um3?TLG`qsoXZfidM1G@Xto|+)Gp=VaS;Q^9D6v=9A zD>#=4Ano&cVAicz1Lcqje*g}Ec0HrKfAs*ZXNAq1<|_lpmo==DKZL81tN)a z-G$7_Zqvrk!pe$hqqYtX!@JFyp6HMtm!DR zlY%zt)46}pc&GU@O5HcDdK3`1gJ_^hRfR&SkCYK(7=R>uMx>}8RhI`yOL*WM)W?DK zd0>f^Fa5DbD2!_Kr?c<^^IC=K{kB<@x5 zk$1vQb~leE3UKtFT;Jvph*;*-lWW8bLCF!qLW$cXy+TXr@ad&Qi)bp0anoS zpc={A)@G=~8PB3aVN#6)WyEEr;5gAbX#X_(I$X6; zYpSX{&_t+i#6PmJ^0%_Jm6*0ZSo(JyIABWG_ol_VE?acLZPV(9(0h|=CK;f}D(n=h zH}=5R*n3cbAWn;2{Pym{R zy1w&fY{!B9--3Im@f>2Rti&3}gO=5fmc5Nk_uLGR9zYUnB;q6423g?ViKSTj!bo(N z;35C#KI82u-qJ4{Gf19eyVUlUW%|^ zZnCIfP7;y+_-`g5|IbPi^%ca4`U?_-{WBAUA;nq3Pmb&tjVjJW{j(BKKdjOErbeS) zu{%)Dotu!~`sIJ|mMlEx{_fPMF3&yt4!*}{=)Lxad&l5N;yDtHBLSza865qC)RtDR zEzNTQ$I=Twxjl$hva*tBC1{|2c0A9QyeEzMpx1&~aRXK^t{J*{-KFPtZ@v9|LL_>( zFq5pc7*d#lFa&5!Sq>Ugk%wTXYPEvD6H=0eMi-=`m$Q@5wh937R(}&TIUbMRpz@FH=p^muMS&k8rPW&v5Uw3|(oN%o@i?AX(9{eMj0e z=|;zbye%X!HEJd)P*|Sr9279#aqQ@Y0n?{$9=Lcxs@J0TE4-I}RLfhl^rG*&<(K_F zUwy@Y^V+`y!q?sCv2DYDAOYd)Z}@Ln_qX4s&#w5cTltGm=(3C6OBdC;FPKx|J8x!c z@AsyKx#Dxexm&kxJ(ymrFTJ)z(*WQ-$UTbhwHv+nPP8mmW^jxPQY+dck!Yn(GBCl| zkS7UDcIeQPG+ujYNI(&)epEv|1C8I--hO0z57$xcyu3ne{CQ(R;BWX0{zm~B2aNYrwV0HSx8{J;1$)?@1OKiJ7vbWif-(1RyDDC0Urd(C)7@ec}NqAJW4iP}%mf zbm-iNbeE}?u#}fR3L^cV^!xa?mYqBIAtni6fpfz(#K5@GYdg|=k%dN4+nB*IQJC7% zz*}ePoH|fP)rD#VciPxq#I!);i-%JJsPv!`K;iJCfOym2c+zupr{{E{*RZ44w4wK4 zhUN){sTFNBOX{3j)0j#J>OV=q>OxJ619fN}DGajWNdM=ZG3C0HJC*5|F-luRx+T-!eR#IDS=86u9ga*$qLhV6wmY2 a9sdtN6eHRrdyqB&0000AvglfA9NypXa{#=A1b*&&-_9nK?6&dOB)k#LUD105bLa$_BV6=HEq#kGmWEawY(P zYgJuY!N_}RGo8TO$oTXsB$&89>#C*cCdYLmNX~ke#Hv9KA93kET{$`$PbI2&f<=QO zbYEuG&fq#8;U|Hp%+iMX($XltD84sh%`HcA9=yrw*x5Rd?dw|aj_wW|b=kga#C;uk zY)LO?99@%_7kX6dzR(&*!tnq4;>`zco!?9(Az&zTo|L_j^WL&gF7wJuI**)H&y&sO z9l;NhRvPV@eM$C25(Y1oLfTY%Qu06J{1!LY%l6`?e{u8in|(1@!4MJk2$1+uIsPqnf+k()k8h#rg7tMJHVtWaqYT zq|_R>T}xsUyk)<9e2b1o1pB702Pc9ve?7kQpF2}x}2=dBPVaUdm7-ZjF+bUL0vak))KQnKW)qx!vgbJE?)QXqi+7Po!iYjGEI9xeX+3}trhX=ZOA z6m<4$ajUa5?TbuamQOsfYFx!_%v5Pca-z3$eHCN9QVeZN0(`DY*CwYcn=Z{IwS{|W zMVA?tHKL`t<(1kV)n+5idi^{`iXLpvnO=;Rx{T4}wriDGR@79T*3GDl#qU(VPNH?_ z+WNh=8;jQwV zM#imv9eB3r+LQaLX%UgUmS$Q-V|+Ygp>ovUbJ{jiX~_q+go2a38CD$M(o|A(oS*f( zh?L!-@KukR?4c%)OIZBg${L2g5L6Pa=XF(yBP@&9b|agsWh)uYDy{MN@*W9zbE^QG zPZ8wOAg?zDskn|*wf&j@!i7Pbw6fw_Jr}n|+l>O-_8a2*TEQA7y+XU@NUD_gnXUKG z2}$1=_w*$M6~;^rw4#*yT22U!%e#`&t(A(xyf|-T(y3T1sVLvn_}AGKzdo!w)-*Uq z)`#%}qna5)jZjh2p>&4DK;ogEbdo#F?UZ%H>ljUbLLNV;50EQ$-zmX5OZ~Oiu>6ZIQR6g&! zPTyC(E=$qrR?zuYogtRne89+%HynZlT2P=QPE)k~RavpYct9<_leX;S(cUYWmJ%5i zw<#|0L;Epc1diZ!djsOtxXCrexN0iPy+W$%xrf_3!-ktsYsF?BfO_-+rz;1%p|X0Z z`xS4h<)pP{yf5Y2%`K?M%L1lRyQRhGg2R@R1BO$0TUeSMPUR$cJ)j;QyWQ-2SYJ1? z%~^ILTzh8y5rPT)29-&Qo@%PiVei|f)aGz{7xO>5>77{OmMi}>lo?rwpOta_aN2a} zZ_L3$CVhl%C4|)F%yc_!V?s)E@;~94fP)o1CTwgW@3F@BcS<{+x8_h1m|gj-8eT8~ z{P{;v_nE3QwfJ#=Vz7jq`qgMV1n|+2J0HNKgTY17#cGz07^gpi;87-UU+o*XC;A3g zg??@@etFPbu_%d$CSm+feh%;vd6_sgJ6ydmIB8OZ2ObCNBuk-&Tg}J-dX|>uJe}kmEmBH)Q7uAac~6f=i$joy zJK0c6OM9t_Ef1k*Ry3>%RVQV4P_zwS5s^T+u`MbCH zd6?wSSFRIE`|C9((s}H4ZYxc^RT{P)UbYCc^d0IW&aSPITSpqAIQF6g6&D^@VVnrOzTa^&s3buD4Zh79z^>7JLQH+- zqYS8QcLF8+03Y|4eD30R)L9O+_7gvyxH&uXehWGsGF8ox(YPKFj0 zeO}1^(}~=Cb++)WmDI6QeKp!MtupG%f{wZCy1$n!&RIBjUrS~HF0dp*p%w3uW|XYcuU?@&lSpJS-nf;@|F$`Umi_6zQo)P* zAN?|yXKv+GF@wL}{Z@+e2fPCrPyKWP%8JnsD4{x0N4};B4)_O}kwrPV3fK?Wi2^1> z9|==dt|saLUjuoB-9|amKlwXh1UO#${B=k&OyF9&!@HCh^(P1Z!t`T$%9BxBE^)o# zrb+Lsi5i*!ebE*rcxuhl)knhZ#ON)wO$oi@$3X1Yo6{S=udP&GmK4bkq;tb{^J~U4q82PKlFy7~0oQfA>1ZE&nMwI&x>vEc6U6l>WUM9Dh&x=`RU*Gbxx! zkNtRQF;b=RUB91-eD(xJv`D~Lmt+aUbpk*|itL0+z!SP00+|E6y z`uA#y)}Obo8;y%<&n3om?p6xzZJ%th-0j>wzfmi#6_%M|?B;=zSIm6DyAoM_apC>I zXM6D8M09ojEP0;(Tm6=+iv(2Opx(Oj#^^AOYqkBr2bn&rSZqFl_g%UyrartZl7oXX z-sf{fs&@{EPIHwb9qDY_<^%-#3soQ%QDuSy?jsU+(Fip2|+_ zGrN|zd*<~MKX{Lbhj???lU_IhSOdz4)6#L*Ah zm&9^`M`a&%BRsm}7gG3v#DiB;WAYz|2o$)P`>;wKw>@5~1xl# znaLk1Gsg9W+FM2frk6^A_#Vca3W3`Oq!4wV08%sw2(tG4QPdzk%6LE|<#%m44u|qJ zyU?M#nQ?*VpSqw3iYXL4`rl88NPi0HtH8TIb5i9co;}~0@H+On_0OFWps8>3b*XNL zROE5^A`ad4h3;CKVSt1Kz|T<$S=!5XFZ%6Vi5u+l>6fg(<F3On}Towx%MlobtMeV$xN86aA@wyIsb zpySR3MZYr<`22Zdh0P(}B+{cDNL&Y~SPHU}if;!Las3k+eLw;apzg$Cn=31tX!;`8 zY=|5HvpA^g-d!i?nHGr%`~;Flh)u-a91db%jAcig`GW_KWahiTTh z{}^LvD}yhSsCAb|MoLE2G})=@*?##ViZEif4M<3V`i@tM!^>(*Rgr=M9E%|@2gR-B zJV|}j_)t9!JI+t<`3J6z`iNgqpaz#UNv`wl%dOPql&jUOM&>{9=QR^_l&7V4>`hsJ z^G|jS@;l#xw>et_W*DeS$UNv7$Yq?LHspOA%H3LWvgs9kgq*9fx_t)_w4AYf&erE; zoUk${(?)h)eonZuyEw`pl=f#;ELYvr!4*#ks>oM})C*(SuXf}-zfb9s0fYSo3g&C* zV=nfhl#iZHZ8A?c#4g7pM_Rrg?|bjeon~Ou(U2Voz^zl1+IZQ!G&%DZFh62aK+ek- zIo}{Z&X;+Mut%Mj>T@fUL(+){SDfT6!du|ddt5){zl^BJmNK30o-LWDrxIFSRRt+6 z!mYbqyWs;|mm8gb++|aKrJtx9R=#Vi=s69%I$3gH4DJ(vBFLcl7y^(vnPL2npvJ^j?o{T3??tCz0EKI&uu8tndn zkP*E{3i=Q?WeHe^H6*-O16$ApV$=)$Nqz3J%o|%deE091F8ElmB!tV*#0J2#d^I^`4ktA5yK?Q)z|RG`a?V z6vH1jHr#*xxAsihWpi)FEq@|s`QcppDIGpfxROKBu0<7Fy{apE5|3#IrOxK5OZfiT zjAMJ0KGV~$kv@fkjt4!>L}(9#^U%fwjj7Soc36XR)nDkQ3%8O)y;4K2VSi!6N4Mh@ zw62zp(^}TOjuhC^j`!miC0|X$=v@bbB+t5$f4<4>B;>4L-dJnDu>0!J6a6@}jJN&h z5e^#-V!s9Wub&ovQDiBRQH|Uc+sDm4EBsD^hoLp{bH0m|`La@aQ;Ug8XOExRXK|8f z^?z9pD!y^tS<2~MSIn4a7XMfypgzG#m*nQ%dM@^@iK_bUx$*elFco$VW}e6F=)=J* z3o<(tO11GJCk*0owwI(!QK`Ukf9T;Pd{7*GdM=q|Klu8W#Ibn*K754KV1q`FWw!Tu zep>9~)rzk~X|!cCM0wh46KQ1GO>+TU8SrsBIj*FPcmY7D$cXZ;q6s*Vh)z%o(t;vn zx!K|qj$8j0+q9$yyXv#dz}`dy+B*;=H54B~0IEX%s9R#o6}K@lXi@`Zn-ymH++KpSwT zEpq>t59b$ORT?+07%Qzh8*}&0C2m>=7z55P?UqIjx=Nd z5_RT#G>kXWDMf$`cv#^@V6=CmHr$UfeA!pUv;qQtHbiC6i2y8QN z_e#fn4t6ytGgXu;d7vVGdnkco*$$)h)0U9bYF(y!vQMeBp4HNebA$vCuS3f%VZdk< zA0N@-iIRCci*VNggbxTXO(${yjlZp>R|r93&dmU$WQz=7>t!z_gTUtPbjoj2-X{Rs zrTA$5Jtrt~@cao#5|vM$p+l3M_HC0Ykiw9@7935K_wf*-^|GKh$%+opV7&;?rh9&P zh@9}XUqp-`JNnPs3e9~OrZBIJ1eel)hsimyfZSIAKa-_e!~q3^y@G=z;FN<65|y#S zIBWtzFv3n-*Aa|5F3Z9=zMs!RG6&8j!J;3)knD|vHy=yM(L#G}?m=jXNQ08rzG{Q? z03L8v^?3q`cxQdd42Z9RVo{e%Ga$C`=^7nqlxSf^lZhCTfwJB*!vD&M6QLv2g3NcE zlLNNSl;_UR5*{d}Kf!uIIF!i1cJDS7fMI##KSPmi=TR$DWZKb=cLBWJrF7#XGuhG7 zjcL@fyIHYDII3IRrCBTavFc^BM=uYdvN&GWBrcfogytsZ#mNX@9K+}pNp_= zk9AV-B>m?U~{NIbky_m^|J@%P=#HgBe^ zDfz`6g|`gOJpKE@q~4TH!vrHVNVb%n^e@&ALm85qj|xaBT5I90Ycp`;(u*rwGoyp? zo42?p->1XHi@SD&m=D5+6}|bUFWFw^Ue~(Ns1WQdWg=ux{zyH+AM91|XPZ%d*fiP0agmU%;tlV*!A{7y5(|3pSIw`dLqLknHv_PQBq$*|@+K4(r z(nO>@f;?%pkIO4xr70*Nk#eL*y7x+_=)8hsToX389#3w1KYRW> z*jT10YzQG%=Q$~Vd?jE*NFJ3Q_1xC`bl#coS5x4+(w)Pk{J+G z!)n>NlV4dtbN2@K)QdPtA{jC87jPU@hGv_JS3`DM&#QrL5o|v9pZ!u|C7l8Y!06X} zo>&23nPdehmmoN^p|A!0tiUTr`CHa7lrfP~sQnxYB!UG1e(yGzf9ed??k|R+753Jl z7|p%-Z;}uZWB`691Y{;z%fht0EQ5I=Q=xM!$55sB}?14LLaJP!Sh9=o6Ct`HH&OJAVuCgBpm0G_>L zLgPblVMON9`^+|EfPcuK*NO!3l?TlBFPGtQ7{6XmmBfL}Lk{{Mr*gyq842232l)y! z&EGfE9#VdjQO(a$U8DtYD6#;quA5M_q9pjqqG3-3XgR=iH5haYfFOE#7*m*WlW+;p z?*(QB<`&=?VN8b*zDdAXk|0u&ChUKnuK~u}^00YLP@tffpKM40h@>0qAv>J$ zJrJO6LoW6nQ;Lt_8TqG$3|&uIySi8pIQWB_=t1;Ew5BRl7J?W_#P#Q!jsiS1)t)R& zBm=TT1+G!Pc}xbIpGmNXV5B}zM2aE|pbfY#^zg<53DRF@)}T12BMzF0(fIJ0A+3Z) zF(FCSsFO`ljPqMasO-{OJsw6GD$89qiidf9!om$onI10;i?xPp_7Zxa02^=nHJfV2 zo}1Yu%99UK)~|dQR05$flJ_LP@??KD=@6^q3rd&zl=sq`D155z=wL0%C|=Gl`rS`{ zw-3XN{PCKN>`Mx4Uux^yLNOaIrkrs#Bqr1f%w1cG$Fdo;T7H<^$r|;|#mdi$cevZ* zdUc9(`eHt8@K+4=->Qr*HrT(({2Uj)Bl+GPr7ru{us3&!JKUzXmE_(`3UuU4d?;JL zc1X3KSL^U^==r@m)sd2}-$!fwYMO+)%E6|CLIK_ z##nHbe&&rMSDpx}2%+?FJ^shJ8yjE97(vftaucYh>*)KEqRD9|NrLKH=hV$e9A!~^ z4bADay5RL!GXeJ2_zHiwLYIYD#U!gVUX?0lWn6r52N(6LN{Xi9iK=_HO>X!U%Sq@l zh^!p)kHb1d(Ot9To5AfPe}~eD)OZ0MoXW((BIk$hb?gir611I2@D$KJ^VOg zT4fSfiCU#LYYL*CDCFNS4@bFDJa-HD&yA+x-IPQdMe7%+($&f?mC=n) z%&EO|+G#XLeHlo%(5I?7ol`ugo-_s0FL0#nkfTIT>6E9z50T3{?rk#sL>rRnNM~|9 zbq!>`l)R){K{#)v-}J)R27GTgA_f4XfzXn2${0y<*>7Svs39Rgf5ulzf}LmgT3Eqn z8G!%JRL1Gwj7k#Zh=Le=U`Dd4zH#;|o}L#6L-c(Lz=^Dm0-V6?8-?W5q)|w-V8|R@XK0f;$q`9@OmGmQp4JO_0Zgzau^3zjqT)q;CKx|;eNzuf>j1twm zQVhYEF@QgguW{CYFS%U=FfSW|H*CE2A+vuEH66-Q#2iU|Hp8DbO&^njfDi(!U@PIK z7gKGe-eQ+t4rUUtOnfvN87~ND%ab5b!x8Kexv=DeQHV%lmmMLXSRR33V1Aty75xeT&9+VL0)Pz zHpe~F;-a3{`62`|2n#wq#ktiRT;Lh?1diJGf-G(W%QRhQ=!Jr8$ZYk3OReu(4&Gvg zpl?-6>j!|kPL7>&DkSoxD|)&8W{jZ2fm<;ybWp=h-n|lrVTDs2KpsZq8Q@_M%r>_G z6KCrGAXxq8UNzXk`cExGjmaZsNdrw!&Z+iI)D|i}mo;laGQ-M%`}Lv&JJzx${Fd2` zs~^QJGpsDcGk=sm8SeA2z~=GbR9j%8fE@kpnk59Gk8>W2JHBvC&t8y~%f9?sa~*MT zzP9Q8+4`#QlH>2jX$MYd!H45&7r$Jq^`E!@tm|Bu+=?c(yux?!x_X7iET(66!RFDJ zzB?@ffQNcw6D-yOq*Rav4dB9dVs+0RBr5E*p3whI*rE4%-H25JcTOP^)Sh)#sZzJ+ z$IbOD+T^K=`N6CDCpfKHwv%aj}rTaikoks1a4O*+M}j{W)R#K&nzKm zPg7psVmbDEy1VO-r#xCjVwX&}+zKNECBJ!QguJUSSN_kOkv4T&}pz(^z6}X zGCV=1#|a(xlOI`HtWV8dgfuF4s$*LghD`Amxfcq5mblTfRr+m0tzen&#b|xUxLu~H zK~RBt!`&v4%R?`#kjuBJ$opo+D?{Uaa{a2hC;Ka(&ON7#V0K>#_J%#LVtBRt)u}`s z=j4Xe0jY2@p+RHv*#26?%g93kteo0Q@0;`x2ZCw zUn4`&W-e{5P}Q($ccv`W$#ILg_$6+&?B*0cJk#%;d`QzBB`qy)(UxZZ&Ov}Yokd3N zj~ERapEhGwAMEX1`=zw)*qz1io2i_F)DBjWB|*PHvd4MRPX+%d*|}3CF{@tXNmMe6 zAljfg2r$`|z9qsViLaWuOHk$mb2UHh%?~=#HPf2CPQh;AUrYWW~ zvTV9=)lS#UB-`B5)Kb!Ylg0RA){o3e`19Jl&hb@~zS>>vrFR-^youk^@6>0S` zToim7wzkY|Yt*;aGUy!o{yxd8=*L;orYQC!H#=|pjn&hO>o9B$tJu8TBHmxPPsm-) zM#T(;Z9_uvy1xq;yeeWQV6|}+=O;1%) zGZyIq}2>crU3z2ri)(ut%F~+%S>FR4^Xw()Y-+~&Xp*Ns z$?%1aydpzNIz2aN98}oth>3boYSifQ)J81Of>6k)!`WQWrB;xxXccBzrWe5V*>oMh zon)MEw$@-*!>L`CK}u@x^9-4gfvepI0b8q5QYVXr96{4Q#s2ZelHXxHv~G{GymRer zqyj7m)3yn3z5i4koiIJ!-u=p6QeL|BN+pWd>}TOFOVi01q839$NZ&I_quqb(n~9Wk id-{KKnnu*>l46e`&P3zgUlQEeAE2(Hqg<+p4E|raIYd(c literal 0 HcmV?d00001 diff --git a/agent-mobile/artimobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/agent-mobile/artimobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..4c19a13c239cb67b8a2134ddd5f325db1d2d5bee GIT binary patch literal 15523 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 BIP(Ai literal 0 HcmV?d00001 diff --git a/agent-mobile/artimobile/android/app/src/main/res/values/strings.xml b/agent-mobile/artimobile/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..c15805f --- /dev/null +++ b/agent-mobile/artimobile/android/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + artimobile + diff --git a/agent-mobile/artimobile/android/app/src/main/res/values/styles.xml b/agent-mobile/artimobile/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..7ba83a2 --- /dev/null +++ b/agent-mobile/artimobile/android/app/src/main/res/values/styles.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/agent-mobile/artimobile/android/build.gradle b/agent-mobile/artimobile/android/build.gradle new file mode 100644 index 0000000..cb9d623 --- /dev/null +++ b/agent-mobile/artimobile/android/build.gradle @@ -0,0 +1,21 @@ +buildscript { + ext { + buildToolsVersion = "34.0.0" + minSdkVersion = 21 + compileSdkVersion = 34 + targetSdkVersion = 34 + ndkVersion = "25.1.8937393" + kotlinVersion = "1.8.0" + } + repositories { + google() + mavenCentral() + } + dependencies { + classpath("com.android.tools.build:gradle") + classpath("com.facebook.react:react-native-gradle-plugin") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") + } +} + +apply plugin: "com.facebook.react.rootproject" diff --git a/agent-mobile/artimobile/android/gradle.properties b/agent-mobile/artimobile/android/gradle.properties new file mode 100644 index 0000000..a46a5b9 --- /dev/null +++ b/agent-mobile/artimobile/android/gradle.properties @@ -0,0 +1,41 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m +org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true + +# Use this property to specify which architecture you want to build. +# You can also override it from the CLI using +# ./gradlew -PreactNativeArchitectures=x86_64 +reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 + +# Use this property to enable support to the new architecture. +# This will allow you to use TurboModules and the Fabric render in +# your application. You should enable this flag either if you want +# to write custom TurboModules/Fabric components OR use libraries that +# are providing them. +newArchEnabled=false + +# Use this property to enable or disable the Hermes JS engine. +# If set to false, you will be using JSC instead. +hermesEnabled=true diff --git a/agent-mobile/artimobile/android/gradle/wrapper/gradle-wrapper.jar b/agent-mobile/artimobile/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..7f93135c49b765f8051ef9d0a6055ff8e46073d8 GIT binary patch literal 63721 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鯊%1Et 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⁢ zv5o9#E7!G0XmdzfsS{efPNi`1b44~SZ4Z8fuX!I}#8g+(wxzQwUT#Xb2(tbY1+EUhGKoT@KEU9Ktl>_0 z%bjDJg;#*gtJZv!-Zs`?^}v5eKmnbjqlvnSzE@_SP|LG_PJ6CYU+6zY6>92%E+ z=j@TZf-iW4(%U{lnYxQA;7Q!b;^brF8n0D>)`q5>|WDDXLrqYU_tKN2>=#@~OE7grMnNh?UOz-O~6 z6%rHy{#h9K0AT+lDC7q4{hw^|q6*Ry;;L%Q@)Ga}$60_q%D)rv(CtS$CQbpq9|y1e zRSrN4;$Jyl{m5bZw`$8TGvb}(LpY{-cQ)fcyJv7l3S52TLXVDsphtv&aPuDk1OzCA z4A^QtC(!11`IsNx_HnSy?>EKpHJWT^wmS~hc^p^zIIh@9f6U@I2 zC=Mve{j2^)mS#U$e{@Q?SO6%LDsXz@SY+=cK_QMmXBIU)j!$ajc-zLx3V60EXJ!qC zi<%2x8Q24YN+&8U@CIlN zrZkcT9yh%LrlGS9`G)KdP(@9Eo-AQz@8GEFWcb7U=a0H^ZVbLmz{+&M7W(nXJ4sN8 zJLR7eeK(K8`2-}j(T7JsO`L!+CvbueT%izanm-^A1Dn{`1Nw`9P?cq;7no+XfC`K(GO9?O^5zNIt4M+M8LM0=7Gz8UA@Z0N+lg+cX)NfazRu z5D)~HA^(u%w^cz+@2@_#S|u>GpB+j4KzQ^&Wcl9f z&hG#bCA(Yk0D&t&aJE^xME^&E-&xGHhXn%}psEIj641H+Nl-}boj;)Zt*t(4wZ5DN z@GXF$bL=&pBq-#vkTkh>7hl%K5|3 z{`Vn9b$iR-SoGENp}bn4;fR3>9sA%X2@1L3aE9yTra;Wb#_`xWwLSLdfu+PAu+o3| zGVnpzPr=ch{uuoHjtw7+_!L_2;knQ!DuDl0R`|%jr+}jFzXtrHIKc323?JO{l&;VF z*L1+}JU7%QJOg|5|Tc|D8fN zJORAg=_vsy{ak|o);@)Yh8Lkcg@$FG3k@ep36BRa^>~UmnRPziS>Z=`Jb2x*Q#`%A zU*i3&Vg?TluO@X0O;r2Jl6LKLUOVhSqg1*qOt^|8*c7 zo(298@+r$k_wQNGHv{|$tW(T8L+4_`FQ{kEW5Jgg{yf7ey4ss_(SNKfz(N9lx&a;< je(UuV8hP?p&}TPdm1I$XmG#(RzlD&B2izSj9sl%y5~4qc literal 0 HcmV?d00001 diff --git a/agent-mobile/artimobile/android/gradle/wrapper/gradle-wrapper.properties b/agent-mobile/artimobile/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..d11cdd9 --- /dev/null +++ b/agent-mobile/artimobile/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/agent-mobile/artimobile/android/gradlew b/agent-mobile/artimobile/android/gradlew new file mode 100644 index 0000000..0adc8e1 --- /dev/null +++ b/agent-mobile/artimobile/android/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/agent-mobile/artimobile/android/gradlew.bat b/agent-mobile/artimobile/android/gradlew.bat new file mode 100644 index 0000000..6689b85 --- /dev/null +++ b/agent-mobile/artimobile/android/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/agent-mobile/artimobile/android/settings.gradle b/agent-mobile/artimobile/android/settings.gradle new file mode 100644 index 0000000..42d78eb --- /dev/null +++ b/agent-mobile/artimobile/android/settings.gradle @@ -0,0 +1,4 @@ +rootProject.name = 'artimobile' +apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) +include ':app' +includeBuild('../node_modules/@react-native/gradle-plugin') diff --git a/agent-mobile/artimobile/app.json b/agent-mobile/artimobile/app.json new file mode 100644 index 0000000..a08ae66 --- /dev/null +++ b/agent-mobile/artimobile/app.json @@ -0,0 +1,4 @@ +{ + "name": "artimobile", + "displayName": "artimobile" +} diff --git a/agent-mobile/artimobile/babel.config.js b/agent-mobile/artimobile/babel.config.js new file mode 100644 index 0000000..f7b3da3 --- /dev/null +++ b/agent-mobile/artimobile/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: ['module:@react-native/babel-preset'], +}; diff --git a/agent-mobile/artimobile/index.js b/agent-mobile/artimobile/index.js new file mode 100644 index 0000000..a850d03 --- /dev/null +++ b/agent-mobile/artimobile/index.js @@ -0,0 +1,9 @@ +/** + * @format + */ + +import {AppRegistry} from 'react-native'; +import App from './App'; +import {name as appName} from './app.json'; + +AppRegistry.registerComponent(appName, () => App); diff --git a/agent-mobile/artimobile/ios/.xcode.env b/agent-mobile/artimobile/ios/.xcode.env new file mode 100644 index 0000000..3d5782c --- /dev/null +++ b/agent-mobile/artimobile/ios/.xcode.env @@ -0,0 +1,11 @@ +# This `.xcode.env` file is versioned and is used to source the environment +# used when running script phases inside Xcode. +# To customize your local environment, you can create an `.xcode.env.local` +# file that is not versioned. + +# NODE_BINARY variable contains the PATH to the node executable. +# +# Customize the NODE_BINARY variable here. +# For example, to use nvm with brew, add the following line +# . "$(brew --prefix nvm)/nvm.sh" --no-use +export NODE_BINARY=$(command -v node) diff --git a/agent-mobile/artimobile/ios/Podfile b/agent-mobile/artimobile/ios/Podfile new file mode 100644 index 0000000..13a7005 --- /dev/null +++ b/agent-mobile/artimobile/ios/Podfile @@ -0,0 +1,55 @@ +# Resolve react_native_pods.rb with node to allow for hoisting +require Pod::Executable.execute_command('node', ['-p', + 'require.resolve( + "react-native/scripts/react_native_pods.rb", + {paths: [process.argv[1]]}, + )', __dir__]).strip + +platform :ios, min_ios_version_supported +prepare_react_native_project! + +# If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set. +# because `react-native-flipper` depends on (FlipperKit,...) that will be excluded +# +# To fix this you can also exclude `react-native-flipper` using a `react-native.config.js` +# ```js +# module.exports = { +# dependencies: { +# ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}), +# ``` +flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled + +linkage = ENV['USE_FRAMEWORKS'] +if linkage != nil + Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green + use_frameworks! :linkage => linkage.to_sym +end + +target 'artimobile' do + config = use_native_modules! + + use_react_native!( + :path => config[:reactNativePath], + # Enables Flipper. + # + # Note that if you have use_frameworks! enabled, Flipper will not work and + # you should disable the next line. + :flipper_configuration => flipper_config, + # An absolute path to your application root. + :app_path => "#{Pod::Config.instance.installation_root}/.." + ) + + target 'artimobileTests' do + inherit! :complete + # Pods for testing + end + + post_install do |installer| + # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 + react_native_post_install( + installer, + config[:reactNativePath], + :mac_catalyst_enabled => false + ) + end +end diff --git a/agent-mobile/artimobile/ios/artimobile.xcodeproj/project.pbxproj b/agent-mobile/artimobile/ios/artimobile.xcodeproj/project.pbxproj new file mode 100644 index 0000000..57045c7 --- /dev/null +++ b/agent-mobile/artimobile/ios/artimobile.xcodeproj/project.pbxproj @@ -0,0 +1,684 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 00E356F31AD99517003FC87E /* artimobileTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* artimobileTests.m */; }; + 0C80B921A6F3F58F76C31292 /* libPods-artimobile.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-artimobile.a */; }; + 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; + 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; + 7699B88040F8A987B510C191 /* libPods-artimobile-artimobileTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-artimobile-artimobileTests.a */; }; + 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 13B07F861A680F5B00A75B9A; + remoteInfo = artimobile; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 00E356EE1AD99517003FC87E /* artimobileTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = artimobileTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 00E356F21AD99517003FC87E /* artimobileTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = artimobileTests.m; sourceTree = ""; }; + 13B07F961A680F5B00A75B9A /* artimobile.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = artimobile.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = artimobile/AppDelegate.h; sourceTree = ""; }; + 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = artimobile/AppDelegate.mm; sourceTree = ""; }; + 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = artimobile/Images.xcassets; sourceTree = ""; }; + 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = artimobile/Info.plist; sourceTree = ""; }; + 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = artimobile/main.m; sourceTree = ""; }; + 19F6CBCC0A4E27FBF8BF4A61 /* libPods-artimobile-artimobileTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-artimobile-artimobileTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B4392A12AC88292D35C810B /* Pods-artimobile.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-artimobile.debug.xcconfig"; path = "Target Support Files/Pods-artimobile/Pods-artimobile.debug.xcconfig"; sourceTree = ""; }; + 5709B34CF0A7D63546082F79 /* Pods-artimobile.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-artimobile.release.xcconfig"; path = "Target Support Files/Pods-artimobile/Pods-artimobile.release.xcconfig"; sourceTree = ""; }; + 5B7EB9410499542E8C5724F5 /* Pods-artimobile-artimobileTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-artimobile-artimobileTests.debug.xcconfig"; path = "Target Support Files/Pods-artimobile-artimobileTests/Pods-artimobile-artimobileTests.debug.xcconfig"; sourceTree = ""; }; + 5DCACB8F33CDC322A6C60F78 /* libPods-artimobile.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-artimobile.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = artimobile/LaunchScreen.storyboard; sourceTree = ""; }; + 89C6BE57DB24E9ADA2F236DE /* Pods-artimobile-artimobileTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-artimobile-artimobileTests.release.xcconfig"; path = "Target Support Files/Pods-artimobile-artimobileTests/Pods-artimobile-artimobileTests.release.xcconfig"; sourceTree = ""; }; + ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 00E356EB1AD99517003FC87E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7699B88040F8A987B510C191 /* libPods-artimobile-artimobileTests.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C80B921A6F3F58F76C31292 /* libPods-artimobile.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 00E356EF1AD99517003FC87E /* artimobileTests */ = { + isa = PBXGroup; + children = ( + 00E356F21AD99517003FC87E /* artimobileTests.m */, + 00E356F01AD99517003FC87E /* Supporting Files */, + ); + path = artimobileTests; + sourceTree = ""; + }; + 00E356F01AD99517003FC87E /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 00E356F11AD99517003FC87E /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 13B07FAE1A68108700A75B9A /* artimobile */ = { + isa = PBXGroup; + children = ( + 13B07FAF1A68108700A75B9A /* AppDelegate.h */, + 13B07FB01A68108700A75B9A /* AppDelegate.mm */, + 13B07FB51A68108700A75B9A /* Images.xcassets */, + 13B07FB61A68108700A75B9A /* Info.plist */, + 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, + 13B07FB71A68108700A75B9A /* main.m */, + ); + name = artimobile; + sourceTree = ""; + }; + 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { + isa = PBXGroup; + children = ( + ED297162215061F000B7C4FE /* JavaScriptCore.framework */, + 5DCACB8F33CDC322A6C60F78 /* libPods-artimobile.a */, + 19F6CBCC0A4E27FBF8BF4A61 /* libPods-artimobile-artimobileTests.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 832341AE1AAA6A7D00B99B32 /* Libraries */ = { + isa = PBXGroup; + children = ( + ); + name = Libraries; + sourceTree = ""; + }; + 83CBB9F61A601CBA00E9B192 = { + isa = PBXGroup; + children = ( + 13B07FAE1A68108700A75B9A /* artimobile */, + 832341AE1AAA6A7D00B99B32 /* Libraries */, + 00E356EF1AD99517003FC87E /* artimobileTests */, + 83CBBA001A601CBA00E9B192 /* Products */, + 2D16E6871FA4F8E400B85C8A /* Frameworks */, + BBD78D7AC51CEA395F1C20DB /* Pods */, + ); + indentWidth = 2; + sourceTree = ""; + tabWidth = 2; + usesTabs = 0; + }; + 83CBBA001A601CBA00E9B192 /* Products */ = { + isa = PBXGroup; + children = ( + 13B07F961A680F5B00A75B9A /* artimobile.app */, + 00E356EE1AD99517003FC87E /* artimobileTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + BBD78D7AC51CEA395F1C20DB /* Pods */ = { + isa = PBXGroup; + children = ( + 3B4392A12AC88292D35C810B /* Pods-artimobile.debug.xcconfig */, + 5709B34CF0A7D63546082F79 /* Pods-artimobile.release.xcconfig */, + 5B7EB9410499542E8C5724F5 /* Pods-artimobile-artimobileTests.debug.xcconfig */, + 89C6BE57DB24E9ADA2F236DE /* Pods-artimobile-artimobileTests.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 00E356ED1AD99517003FC87E /* artimobileTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "artimobileTests" */; + buildPhases = ( + A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */, + 00E356EA1AD99517003FC87E /* Sources */, + 00E356EB1AD99517003FC87E /* Frameworks */, + 00E356EC1AD99517003FC87E /* Resources */, + C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */, + F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + 00E356F51AD99517003FC87E /* PBXTargetDependency */, + ); + name = artimobileTests; + productName = artimobileTests; + productReference = 00E356EE1AD99517003FC87E /* artimobileTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 13B07F861A680F5B00A75B9A /* artimobile */ = { + isa = PBXNativeTarget; + buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "artimobile" */; + buildPhases = ( + C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */, + 13B07F871A680F5B00A75B9A /* Sources */, + 13B07F8C1A680F5B00A75B9A /* Frameworks */, + 13B07F8E1A680F5B00A75B9A /* Resources */, + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, + 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */, + E235C05ADACE081382539298 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = artimobile; + productName = artimobile; + productReference = 13B07F961A680F5B00A75B9A /* artimobile.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 83CBB9F71A601CBA00E9B192 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1210; + TargetAttributes = { + 00E356ED1AD99517003FC87E = { + CreatedOnToolsVersion = 6.2; + TestTargetID = 13B07F861A680F5B00A75B9A; + }; + 13B07F861A680F5B00A75B9A = { + LastSwiftMigration = 1120; + }; + }; + }; + buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "artimobile" */; + compatibilityVersion = "Xcode 12.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 83CBB9F61A601CBA00E9B192; + productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 13B07F861A680F5B00A75B9A /* artimobile */, + 00E356ED1AD99517003FC87E /* artimobileTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 00E356EC1AD99517003FC87E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F8E1A680F5B00A75B9A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/.xcode.env.local", + "$(SRCROOT)/.xcode.env", + ); + name = "Bundle React Native code and images"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; + }; + 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-artimobile/Pods-artimobile-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-artimobile/Pods-artimobile-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-artimobile/Pods-artimobile-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-artimobile-artimobileTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-artimobile-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-artimobile-artimobileTests/Pods-artimobile-artimobileTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-artimobile-artimobileTests/Pods-artimobile-artimobileTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-artimobile-artimobileTests/Pods-artimobile-artimobileTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-artimobile/Pods-artimobile-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-artimobile/Pods-artimobile-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-artimobile/Pods-artimobile-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-artimobile-artimobileTests/Pods-artimobile-artimobileTests-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-artimobile-artimobileTests/Pods-artimobile-artimobileTests-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-artimobile-artimobileTests/Pods-artimobile-artimobileTests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 00E356EA1AD99517003FC87E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 00E356F31AD99517003FC87E /* artimobileTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F871A680F5B00A75B9A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */, + 13B07FC11A68108700A75B9A /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 00E356F51AD99517003FC87E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 13B07F861A680F5B00A75B9A /* artimobile */; + targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 00E356F61AD99517003FC87E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5B7EB9410499542E8C5724F5 /* Pods-artimobile-artimobileTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = artimobileTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + OTHER_LDFLAGS = ( + "-ObjC", + "-lc++", + "$(inherited)", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/artimobile.app/artimobile"; + }; + name = Debug; + }; + 00E356F71AD99517003FC87E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 89C6BE57DB24E9ADA2F236DE /* Pods-artimobile-artimobileTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + COPY_PHASE_STRIP = NO; + INFOPLIST_FILE = artimobileTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + OTHER_LDFLAGS = ( + "-ObjC", + "-lc++", + "$(inherited)", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/artimobile.app/artimobile"; + }; + name = Release; + }; + 13B07F941A680F5B00A75B9A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-artimobile.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = artimobile/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = artimobile; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 13B07F951A680F5B00A75B9A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-artimobile.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = 1; + INFOPLIST_FILE = artimobile/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = artimobile; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; + 83CBBA201A601CBA00E9B192 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.4; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + "\"$(inherited)\"", + ); + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DFOLLY_NO_CONFIG", + "-DFOLLY_MOBILE=1", + "-DFOLLY_USE_LIBCPP=1", + "-DFOLLY_CFG_NO_COROUTINES=1", + ); + SDKROOT = iphoneos; + }; + name = Debug; + }; + 83CBBA211A601CBA00E9B192 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.4; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + "\"$(inherited)\"", + ); + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DFOLLY_NO_CONFIG", + "-DFOLLY_MOBILE=1", + "-DFOLLY_USE_LIBCPP=1", + "-DFOLLY_CFG_NO_COROUTINES=1", + ); + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "artimobileTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 00E356F61AD99517003FC87E /* Debug */, + 00E356F71AD99517003FC87E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "artimobile" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 13B07F941A680F5B00A75B9A /* Debug */, + 13B07F951A680F5B00A75B9A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "artimobile" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 83CBBA201A601CBA00E9B192 /* Debug */, + 83CBBA211A601CBA00E9B192 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; +} diff --git a/agent-mobile/artimobile/ios/artimobile.xcodeproj/xcshareddata/xcschemes/artimobile.xcscheme b/agent-mobile/artimobile/ios/artimobile.xcodeproj/xcshareddata/xcschemes/artimobile.xcscheme new file mode 100644 index 0000000..311c8ff --- /dev/null +++ b/agent-mobile/artimobile/ios/artimobile.xcodeproj/xcshareddata/xcschemes/artimobile.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/agent-mobile/artimobile/ios/artimobile/AppDelegate.h b/agent-mobile/artimobile/ios/artimobile/AppDelegate.h new file mode 100644 index 0000000..5d28082 --- /dev/null +++ b/agent-mobile/artimobile/ios/artimobile/AppDelegate.h @@ -0,0 +1,6 @@ +#import +#import + +@interface AppDelegate : RCTAppDelegate + +@end diff --git a/agent-mobile/artimobile/ios/artimobile/AppDelegate.mm b/agent-mobile/artimobile/ios/artimobile/AppDelegate.mm new file mode 100644 index 0000000..5b1381c --- /dev/null +++ b/agent-mobile/artimobile/ios/artimobile/AppDelegate.mm @@ -0,0 +1,31 @@ +#import "AppDelegate.h" + +#import + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + self.moduleName = @"artimobile"; + // You can add your custom initial props in the dictionary below. + // They will be passed down to the ViewController used by React Native. + self.initialProps = @{}; + + return [super application:application didFinishLaunchingWithOptions:launchOptions]; +} + +- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge +{ + return [self getBundleURL]; +} + +- (NSURL *)getBundleURL +{ +#if DEBUG + return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; +#else + return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; +#endif +} + +@end diff --git a/agent-mobile/artimobile/ios/artimobile/Images.xcassets/AppIcon.appiconset/Contents.json b/agent-mobile/artimobile/ios/artimobile/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..8121323 --- /dev/null +++ b/agent-mobile/artimobile/ios/artimobile/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,53 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/agent-mobile/artimobile/ios/artimobile/Images.xcassets/Contents.json b/agent-mobile/artimobile/ios/artimobile/Images.xcassets/Contents.json new file mode 100644 index 0000000..2d92bd5 --- /dev/null +++ b/agent-mobile/artimobile/ios/artimobile/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/agent-mobile/artimobile/ios/artimobile/Info.plist b/agent-mobile/artimobile/ios/artimobile/Info.plist new file mode 100644 index 0000000..7e9a3ac --- /dev/null +++ b/agent-mobile/artimobile/ios/artimobile/Info.plist @@ -0,0 +1,52 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + artimobile + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + LSRequiresIPhoneOS + + NSAppTransportSecurity + + + NSAllowsArbitraryLoads + + NSAllowsLocalNetworking + + + NSLocationWhenInUseUsageDescription + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/agent-mobile/artimobile/ios/artimobile/LaunchScreen.storyboard b/agent-mobile/artimobile/ios/artimobile/LaunchScreen.storyboard new file mode 100644 index 0000000..4d8af90 --- /dev/null +++ b/agent-mobile/artimobile/ios/artimobile/LaunchScreen.storyboard @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/agent-mobile/artimobile/ios/artimobile/main.m b/agent-mobile/artimobile/ios/artimobile/main.m new file mode 100644 index 0000000..d645c72 --- /dev/null +++ b/agent-mobile/artimobile/ios/artimobile/main.m @@ -0,0 +1,10 @@ +#import + +#import "AppDelegate.h" + +int main(int argc, char *argv[]) +{ + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/agent-mobile/artimobile/ios/artimobileTests/Info.plist b/agent-mobile/artimobile/ios/artimobileTests/Info.plist new file mode 100644 index 0000000..ba72822 --- /dev/null +++ b/agent-mobile/artimobile/ios/artimobileTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/agent-mobile/artimobile/ios/artimobileTests/artimobileTests.m b/agent-mobile/artimobile/ios/artimobileTests/artimobileTests.m new file mode 100644 index 0000000..9513d8c --- /dev/null +++ b/agent-mobile/artimobile/ios/artimobileTests/artimobileTests.m @@ -0,0 +1,66 @@ +#import +#import + +#import +#import + +#define TIMEOUT_SECONDS 600 +#define TEXT_TO_LOOK_FOR @"Welcome to React" + +@interface artimobileTests : XCTestCase + +@end + +@implementation artimobileTests + +- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test +{ + if (test(view)) { + return YES; + } + for (UIView *subview in [view subviews]) { + if ([self findSubviewInView:subview matching:test]) { + return YES; + } + } + return NO; +} + +- (void)testRendersWelcomeScreen +{ + UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; + NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; + BOOL foundElement = NO; + + __block NSString *redboxError = nil; +#ifdef DEBUG + RCTSetLogFunction( + ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { + if (level >= RCTLogLevelError) { + redboxError = message; + } + }); +#endif + + while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { + [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + + foundElement = [self findSubviewInView:vc.view + matching:^BOOL(UIView *view) { + if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { + return YES; + } + return NO; + }]; + } + +#ifdef DEBUG + RCTSetLogFunction(RCTDefaultLogFunction); +#endif + + XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); + XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); +} + +@end diff --git a/agent-mobile/artimobile/jest.config.js b/agent-mobile/artimobile/jest.config.js new file mode 100644 index 0000000..8eb675e --- /dev/null +++ b/agent-mobile/artimobile/jest.config.js @@ -0,0 +1,3 @@ +module.exports = { + preset: 'react-native', +}; diff --git a/agent-mobile/artimobile/metro.config.js b/agent-mobile/artimobile/metro.config.js new file mode 100644 index 0000000..ad8f87b --- /dev/null +++ b/agent-mobile/artimobile/metro.config.js @@ -0,0 +1,11 @@ +const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config'); + +/** + * Metro configuration + * https://facebook.github.io/metro/docs/configuration + * + * @type {import('metro-config').MetroConfig} + */ +const config = {}; + +module.exports = mergeConfig(getDefaultConfig(__dirname), config); diff --git a/agent-mobile/artimobile/package.json b/agent-mobile/artimobile/package.json new file mode 100644 index 0000000..238dd3d --- /dev/null +++ b/agent-mobile/artimobile/package.json @@ -0,0 +1,36 @@ +{ + "name": "artimobile", + "version": "0.0.1", + "private": true, + "scripts": { + "android": "react-native run-android", + "ios": "react-native run-ios", + "lint": "eslint .", + "start": "react-native start", + "test": "jest" + }, + "dependencies": { + "react": "18.2.0", + "react-native": "0.73.4" + }, + "devDependencies": { + "@babel/core": "^7.20.0", + "@babel/preset-env": "^7.20.0", + "@babel/runtime": "^7.20.0", + "@react-native/babel-preset": "0.73.21", + "@react-native/eslint-config": "0.73.2", + "@react-native/metro-config": "0.73.5", + "@react-native/typescript-config": "0.73.1", + "@types/react": "^18.2.6", + "@types/react-test-renderer": "^18.0.0", + "babel-jest": "^29.6.3", + "eslint": "^8.19.0", + "jest": "^29.6.3", + "prettier": "2.8.8", + "react-test-renderer": "18.2.0", + "typescript": "5.0.4" + }, + "engines": { + "node": ">=18" + } +} diff --git a/agent-mobile/artimobile/supervisord.pid b/agent-mobile/artimobile/supervisord.pid new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/agent-mobile/artimobile/supervisord.pid @@ -0,0 +1 @@ +7 diff --git a/agent-mobile/artimobile/tsconfig.json b/agent-mobile/artimobile/tsconfig.json new file mode 100644 index 0000000..304ab4e --- /dev/null +++ b/agent-mobile/artimobile/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "@react-native/typescript-config/tsconfig.json" +} diff --git a/agent-mobile/docker.yml b/agent-mobile/docker.yml new file mode 100644 index 0000000..41f8746 --- /dev/null +++ b/agent-mobile/docker.yml @@ -0,0 +1,25 @@ +version: "3.8" +services: + # original https://github.com/budtmo/docker-android + # fork with storage https://github.com/Hadows/docker-android13 + # https://iandroids.github.io/docker-android/ # -e DEVICE="Samsung Galaxy S6" --name android-container budtmo/docker-android-x86-8.1 + android-container: + image: budtmo/docker-android:emulator_14.0 #budtmo/docker-android + container_name: android-container + ports: + - "6081:6080" + - "5554:5554" + - "5555:5555" + environment: + EMULATOR_DEVICE: Samsung Galaxy S10 + WEB_VNC: "true" + devices: + - "/dev/kvm:/dev/kvm" + volumes: + - "/mnt/storage/DEV/workspace/repos/git.d-popov.com/ai-kevin/agent-mobile/artimobile:/home/androidusr/tmp" + - /mnt/apps/docker_volumes/android_emulator/download:/home/androidusr/download + #- "/mnt/apps/docker_volumes/android_emulator/data:/home/androidusr/.android" + #- /mnt/apps/docker_volumes/android_emulator/.android:/home/androidusr/.android + #- /mnt/apps/docker_volumes/android_emulator/android_emulator:/home/androidusr/emulator + working_dir: /home/androidusr/tmp + #command: /bin/bash -c "cd /home/androidusr/tmp && npx react-native run-android" diff --git a/agent-mobile/idea.md b/agent-mobile/idea.md new file mode 100644 index 0000000..2f2aa09 --- /dev/null +++ b/agent-mobile/idea.md @@ -0,0 +1,45 @@ +in vscode, create a new android app that will trigger specific function on physical key press. we should be able to map the specific action in the android OS. +the action will listen on on the microphone and will stream the audio to a server and will show the server responses on the screen +-- +you're in a shell console at a root folder of a new software project. we use vscode-server. +let's create a mobile app (prioritize android, and plan to also support iOS) which will send the audio input to tts llm +plan for the following extesion features in the future: + - ability to listen in the background for a wake word and send the following voice command + - ability to listen on hardware button press, or O buttton hold or other android fast access shortcut intent + + + # + >abc@8625820ec90d:/workspace/repos/git.d-popov.com/ai-kevin/agent-mobile$ npx react-native init artimobile + Run instructions for Android: + • Have an Android emulator running (quickest way to get started), or a device connected. + • cd "/workspace/repos/git.d-popov.com/ai-kevin/agent-mobile/artimobile" && npx react-native run-android + +info 💡 Tip: Make sure that you have set up your development environment correctly, by running npx react-native doctor. To read more about doctor command visit: https://github.com/react-native-community/cli/blob/main/packages/cli-doctor/README.md#doctor + + +#:host +conda search openjdk +conda install -c conda-forge openjdk=17 +java -version + +#:host +sudo apt-get install adb + +#: emu +cd /home/androidusr/tmp && npx react-native run-android +# RUN ln -s ${ANDROID_HOME}/emulator/emulator /usr/bin/ +/emulator/emulator -list-avds +emulator -avd samsung_galaxy_s10_14.0 +# update jdk +FROM budtmo/docker-android:emulator_11.0_v2.0 +RUN apt-get update && \ + apt-get install -y openjdk-17-jdk && \ + apt-get clean; +# Set JAVA_HOME environment variable to Java 17 +ENV JAVA_HOME /usr/lib/jvm/java-17-openjdk-amd64 + +wget https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_linux-x64_bin.tar.gz +tar -xzf openjdk-21.0.2_linux-x64_bin.tar.gz -C /home/androidusr/jdk +export JAVA_HOME=/home/androidusr/jdk +export PATH=$JAVA_HOME/bin:$PATH +source ~/.bashrc \ No newline at end of file From 7fd17ada8083ae04e06985362f31460ff74c226d Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Wed, 14 Feb 2024 18:27:15 +0200 Subject: [PATCH 20/26] compiled successfully --- agent-mobile/artimobile/VoiceHandler.js | 72 +++++++++++++++++++++++++ agent-mobile/artimobile/package.json | 1 + agent-mobile/idea.md | 17 ++++-- 3 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 agent-mobile/artimobile/VoiceHandler.js diff --git a/agent-mobile/artimobile/VoiceHandler.js b/agent-mobile/artimobile/VoiceHandler.js new file mode 100644 index 0000000..c1e2181 --- /dev/null +++ b/agent-mobile/artimobile/VoiceHandler.js @@ -0,0 +1,72 @@ +// VoiceHandler.js +import React, { Component } from 'react'; +import { View, Text, Button } from 'react-native'; +import Voice from '@react-native-voice/voice'; + +class VoiceHandler extends Component { + constructor(props) { + super(props); + this.state = { + recognized: '', + started: '', + results: [], + }; + + Voice.onSpeechStart = this.onSpeechStart.bind(this); + Voice.onSpeechRecognized = this.onSpeechRecognized.bind(this); + Voice.onSpeechResults = this.onSpeechResults.bind(this); + } + + componentWillUnmount() { + Voice.destroy().then(Voice.removeAllListeners); + } + + onSpeechStart(e) { + this.setState({ + started: '√', + }); + } + + onSpeechRecognized(e) { + this.setState({ + recognized: '√', + }); + } + + onSpeechResults(e) { + this.setState({ + results: e.value, + }); + } + + async _startRecognizing(e) { + this.setState({ + recognized: '', + started: '', + results: [], + }); + + try { + await Voice.start('en-US'); + } catch (e) { + console.error(e); + } + } + + render() { + return ( + + Press the button and start speaking. +