feat(qr): add QR code generation and phone number validation utilities
This commit is contained in:
parent
90fafefbe5
commit
93e466ebcf
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -14,6 +14,7 @@ GameObject:
|
||||
- component: {fileID: 4577859410310799261}
|
||||
- component: {fileID: -6245296037342915518}
|
||||
- component: {fileID: 6566017136146807207}
|
||||
- component: {fileID: 5633451267958679388}
|
||||
- component: {fileID: 6824661392768214298}
|
||||
- component: {fileID: -3912971501865491093}
|
||||
m_Layer: 0
|
||||
@ -77,6 +78,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::ComWrapper
|
||||
saveMoneyBetweenSessions: 0
|
||||
enablePrizeChecking: 0
|
||||
keepAlive: 1
|
||||
--- !u!114 &-6245296037342915518
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -103,6 +105,32 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::PrizeSystem
|
||||
prizeErrorSound: {fileID: 0}
|
||||
--- !u!114 &5633451267958679388
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4763496076470024150}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 6e1ef22bfa89b354ea58dcf83572936a, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::PrizeSystemManager
|
||||
givePrizes: 1
|
||||
enableHopper: 0
|
||||
qrCodes:
|
||||
- generateQRCode: 1
|
||||
linkPrefix: https://t.me/
|
||||
suffix: "\u0417\u0434\u0440\u0430\u0432\u0441\u0442\u0432\u0443\u0439\u0442\u0435!
|
||||
\u042F \u0432\u044B\u0438\u0433\u0440\u0430\u043B \u0432 \u0438\u0433\u0440\u0435!
|
||||
\u0416\u0434\u0443 \u0441\u0432\u043E\u0439 \u043F\u0440\u0438\u0437!"
|
||||
- generateQRCode: 1
|
||||
linkPrefix: https://wa.me/
|
||||
suffix: "\u0417\u0434\u0440\u0430\u0432\u0441\u0442\u0432\u0443\u0439\u0442\u0435!
|
||||
\u042F \u0432\u044B\u0438\u0433\u0440\u0430\u043B \u0432 \u0438\u0433\u0440\u0435!
|
||||
\u0416\u0434\u0443 \u0441\u0432\u043E\u0439 \u043F\u0440\u0438\u0437!"
|
||||
_phoneNumberMask: +7XXXXXXXXXX
|
||||
--- !u!114 &6824661392768214298
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -116,7 +144,7 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::RR.Common.Managers.PaymentManager
|
||||
saveMoneyBetweenSessions: 0
|
||||
enableFreePlay: 0
|
||||
enableFreeGame: 0
|
||||
addCreditAction: {fileID: -2889265436170138120, guid: 2bcd2660ca9b64942af0de543d8d7100, type: 3}
|
||||
OnCreditsChanged:
|
||||
m_PersistentCalls:
|
||||
|
||||
@ -989,6 +989,7 @@ RectTransform:
|
||||
- {fileID: 437440678}
|
||||
- {fileID: 630106232}
|
||||
- {fileID: 1291956699}
|
||||
- {fileID: 1765260307}
|
||||
m_Father: {fileID: 1724863672}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.343, y: 0.175}
|
||||
@ -1962,7 +1963,7 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 322.3085, y: -145.87494}
|
||||
m_AnchoredPosition: {x: 300.5153, y: -162.7992}
|
||||
m_SizeDelta: {x: 350, y: 125}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &738730170
|
||||
@ -2199,6 +2200,68 @@ CanvasRenderer:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 925700843}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!1 &954402732
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 954402733}
|
||||
- component: {fileID: 954402734}
|
||||
m_Layer: 5
|
||||
m_Name: Content
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &954402733
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 954402732}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 1794447736}
|
||||
- {fileID: 1251210174}
|
||||
m_Father: {fileID: 1765260307}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: -0.2598877, y: 0.23867798}
|
||||
m_SizeDelta: {x: -0.52001953, y: -0.480011}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &954402734
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 954402732}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 8a8695521f0d02e499659fee002a26c2, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.GridLayoutGroup
|
||||
m_Padding:
|
||||
m_Left: 0
|
||||
m_Right: 0
|
||||
m_Top: 0
|
||||
m_Bottom: 0
|
||||
m_ChildAlignment: 4
|
||||
m_StartCorner: 0
|
||||
m_StartAxis: 0
|
||||
m_CellSize: {x: 200, y: 200}
|
||||
m_Spacing: {x: 50, y: 0}
|
||||
m_Constraint: 0
|
||||
m_ConstraintCount: 2
|
||||
--- !u!1 &1061150945
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -2841,6 +2904,81 @@ CanvasRenderer:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1162184469}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!1 &1251210173
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1251210174}
|
||||
- component: {fileID: 1251210176}
|
||||
- component: {fileID: 1251210175}
|
||||
m_Layer: 5
|
||||
m_Name: GameObject_1
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 0
|
||||
--- !u!224 &1251210174
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1251210173}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 954402733}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 420.47992, y: -135.02136}
|
||||
m_SizeDelta: {x: 200, y: 200}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &1251210175
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1251210173}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 0}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!222 &1251210176
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1251210173}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!1 &1256436979
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -2996,9 +3134,9 @@ RectTransform:
|
||||
m_Father: {fileID: 294888497}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 0.71428573}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 0.31300002}
|
||||
m_AnchoredPosition: {x: -2.4137878, y: 0.44125366}
|
||||
m_SizeDelta: {x: -4.8276, y: 0.8829956}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &1291956700
|
||||
MonoBehaviour:
|
||||
@ -3893,6 +4031,131 @@ CanvasRenderer:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1724863671}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!1 &1765260306
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1765260307}
|
||||
- component: {fileID: 1765260308}
|
||||
m_Layer: 5
|
||||
m_Name: QRPlaceholder
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1765260307
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1765260306}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 954402733}
|
||||
m_Father: {fileID: 294888497}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.0064899777, y: 0.31300002}
|
||||
m_AnchorMax: {x: 1, y: 0.699684}
|
||||
m_AnchoredPosition: {x: -1.4869995, y: 0.58657837}
|
||||
m_SizeDelta: {x: -5.6500244, y: -0.480011}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &1765260308
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1765260306}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: daf828422caf7c74db507420de242849, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: '::'
|
||||
content: {fileID: 954402733}
|
||||
--- !u!1 &1794447735
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1794447736}
|
||||
- component: {fileID: 1794447738}
|
||||
- component: {fileID: 1794447737}
|
||||
m_Layer: 5
|
||||
m_Name: GameObject
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 0
|
||||
--- !u!224 &1794447736
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1794447735}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 954402733}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 170.47992, y: -135.02136}
|
||||
m_SizeDelta: {x: 200, y: 200}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &1794447737
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1794447735}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 0}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!222 &1794447738
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1794447735}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!1 &1871409155
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@ -214,7 +214,7 @@ GameObject:
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
m_IsActive: 0
|
||||
--- !u!224 &28542763
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -1336,7 +1336,7 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 50, y: -50}
|
||||
m_AnchoredPosition: {x: 50, y: -162.5}
|
||||
m_SizeDelta: {x: 400, y: 175}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &254276107
|
||||
@ -8335,10 +8335,10 @@ RectTransform:
|
||||
- {fileID: 247400896}
|
||||
m_Father: {fileID: 1042850270}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 50, y: -50}
|
||||
m_SizeDelta: {x: 400, y: 175}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &1707733840
|
||||
MonoBehaviour:
|
||||
@ -9817,7 +9817,7 @@ GameObject:
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
m_IsActive: 0
|
||||
--- !u!224 &1932206569
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -11027,7 +11027,7 @@ GameObject:
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &2082092898
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -15844,6 +15844,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: Player_New
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1310793554455274069, guid: 0abcb4ad4184fc645aa8c976260b8a2f, type: 3}
|
||||
propertyPath: m_IsActive
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
|
||||
@ -9,17 +9,17 @@ using UnityEngine;
|
||||
/// </summary>
|
||||
public class PrizeSystem : MonoBehaviour
|
||||
{
|
||||
[SerializeField] AudioClip prizeErrorSound;
|
||||
private static PrizeSystem Instance { get; set; }
|
||||
|
||||
public static string key_starts = "STARTS";
|
||||
public static string key_startsNul = "STARTSNUL";
|
||||
public static string key_prizesgiven = "PRIZESGIVEN";
|
||||
public static string key_prizesgivenNul = "PRIZESGIVENNUL";
|
||||
|
||||
private static PrizeSystem instance;
|
||||
private static Coroutine prizeCoroutine;
|
||||
private static bool _prizing = false;
|
||||
|
||||
|
||||
public static readonly string key_starts = "STARTS";
|
||||
public static readonly string key_startsNul = "STARTSNUL";
|
||||
public static readonly string key_prizesgiven = "PRIZESGIVEN";
|
||||
public static readonly string key_prizesgivenNul = "PRIZESGIVENNUL";
|
||||
|
||||
[SerializeField] AudioClip prizeErrorSound;
|
||||
|
||||
//===========================start: PUBLIC API===========================//
|
||||
/// <summary>
|
||||
@ -34,7 +34,15 @@ public class PrizeSystem : MonoBehaviour
|
||||
/// </remarks>
|
||||
public void Initialize()
|
||||
{
|
||||
instance = this;
|
||||
if (Instance != null && Instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
Instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
|
||||
InitCounters();
|
||||
}
|
||||
|
||||
@ -66,8 +74,8 @@ public class PrizeSystem : MonoBehaviour
|
||||
}
|
||||
//
|
||||
// DebugWindow.Message("Выдаю приз");
|
||||
if (prizeCoroutine != null) instance.StopCoroutine(prizeCoroutine);
|
||||
prizeCoroutine = instance.StartCoroutine(instance.Prize());
|
||||
if (prizeCoroutine != null) Instance.StopCoroutine(prizeCoroutine);
|
||||
prizeCoroutine = Instance.StartCoroutine(Instance.Prize());
|
||||
}
|
||||
//===========================end: PUBLIC API===========================//
|
||||
|
||||
@ -77,7 +85,7 @@ public class PrizeSystem : MonoBehaviour
|
||||
_prizing = true;
|
||||
// DebugWindow.Message("Начинаю выдачу");
|
||||
|
||||
float timeout = 10; //сек
|
||||
const float timeout = 10; //сек
|
||||
ComWrapper.Send("301");//включаем мотор
|
||||
float startTime = Time.time;
|
||||
bool success = false;
|
||||
@ -104,12 +112,13 @@ public class PrizeSystem : MonoBehaviour
|
||||
if (!success) AudioManager.Instance.PlaySfx(prizeErrorSound);
|
||||
}
|
||||
|
||||
void IncreasePrizeCounters()
|
||||
private static void IncreasePrizeCounters()
|
||||
{
|
||||
PlayerPrefs.SetInt(key_prizesgiven, PlayerPrefs.GetInt(key_prizesgiven) + 1);
|
||||
PlayerPrefs.SetInt(key_prizesgivenNul, PlayerPrefs.GetInt(key_prizesgivenNul) + 1);
|
||||
}
|
||||
void InitCounters()
|
||||
|
||||
private static void InitCounters()
|
||||
{
|
||||
if (!PlayerPrefs.HasKey(key_starts)) PlayerPrefs.SetInt(key_starts, 0);
|
||||
if (!PlayerPrefs.HasKey(key_startsNul)) PlayerPrefs.SetInt(key_startsNul, 0);
|
||||
|
||||
@ -28,9 +28,10 @@ namespace RR.Game2D.Core.Managers
|
||||
|
||||
// Globals
|
||||
[Header("Globals")]
|
||||
private GameObject globals;
|
||||
[SerializeField] private string globalsPrefabResourcePath = "Prefabs/Global/Globals";
|
||||
[SerializeField] private string AudioMixerResourcePath = "Audio/Master";
|
||||
|
||||
private GameObject globals;
|
||||
|
||||
[Header("Пауза")]
|
||||
public bool IsPaused { get; private set; }
|
||||
@ -71,7 +72,7 @@ namespace RR.Game2D.Core.Managers
|
||||
|
||||
// Singleton
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
private static void Bootstrap()
|
||||
private static void Initialize()
|
||||
{
|
||||
if (Instance != null) return;
|
||||
GameObject go = new GameObject(nameof(GameManager));
|
||||
|
||||
@ -11,6 +11,7 @@ namespace RR.Common.Managers
|
||||
private ComWrapper _comWrapper;
|
||||
private In _in;
|
||||
private PrizeSystem _prizeSystem;
|
||||
private PrizeSystemManager _prizeSystemManager;
|
||||
private PaymentManager _paymentManager;
|
||||
private ComInputToInputSystemAdapter _adapter;
|
||||
|
||||
@ -21,13 +22,15 @@ namespace RR.Common.Managers
|
||||
_comWrapper = GetComponent<ComWrapper>();
|
||||
_in = GetComponent<In>();
|
||||
_prizeSystem = GetComponent<PrizeSystem>();
|
||||
_prizeSystemManager = GetComponent<PrizeSystemManager>();
|
||||
_paymentManager = GetComponent<PaymentManager>();
|
||||
_adapter = GetComponent<ComInputToInputSystemAdapter>();
|
||||
|
||||
if (_settingsManager == null) gameObject.AddComponent<SettingsManager>();
|
||||
if (_comWrapper == null) gameObject.AddComponent<ComWrapper>();
|
||||
if (_in == null) gameObject.AddComponent<In>();
|
||||
if (_prizeSystem == null) gameObject.AddComponent<PrizeSystem>();
|
||||
if (_settingsManager == null) gameObject.AddComponent<SettingsManager>();
|
||||
if (_prizeSystemManager == null) gameObject.AddComponent<PrizeSystemManager>();
|
||||
if (_paymentManager == null) gameObject.AddComponent<PaymentManager>();
|
||||
if (_adapter == null) gameObject.AddComponent<ComInputToInputSystemAdapter>();
|
||||
|
||||
@ -43,6 +46,9 @@ namespace RR.Common.Managers
|
||||
_prizeSystem.Initialize();
|
||||
GameManager.Logger.Log(name, "PrizeSystem successfully initialized.");
|
||||
|
||||
_prizeSystemManager.Initialize();
|
||||
GameManager.Logger.Log(name, "PrizeSystemManager successfully initialized.");
|
||||
|
||||
_paymentManager.Initialize();
|
||||
GameManager.Logger.Log(name, "PaymentManager successfully initialized.");
|
||||
|
||||
|
||||
@ -111,7 +111,7 @@ namespace RR.Common.Managers
|
||||
CreditsCount = newCreditsCount;
|
||||
OnCreditsChanged?.Invoke(CreditsCount);
|
||||
OnCreditAdded?.Invoke(CreditsCount);
|
||||
GameManager.Logger?.Log("PaymentManager", $"Кредит добавлен. Всего: {CreditsCount}");
|
||||
Debug.Log($"Кредит добавлен. Всего: {CreditsCount}", this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -123,7 +123,7 @@ namespace RR.Common.Managers
|
||||
CreditsCount = newCreditsCount;
|
||||
OnCreditsChanged?.Invoke(CreditsCount);
|
||||
OnCreditRemoved?.Invoke(CreditsCount);
|
||||
GameManager.Logger?.Log("PaymentManager", $"Кредит удален. Осталось: {CreditsCount}");
|
||||
Debug.Log($"Кредит удален. Осталось: {CreditsCount}", this);
|
||||
}
|
||||
|
||||
private void SetFreePlay()
|
||||
|
||||
@ -1,16 +1,85 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
using RR.Common.Managers;
|
||||
using UnityEngine;
|
||||
using RR.Common.Utility;
|
||||
using RR.Game2D.Core.Managers;
|
||||
|
||||
|
||||
public class PrizeSystemManager : MonoBehaviour
|
||||
{
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
void Start()
|
||||
public static PrizeSystemManager Instance { get; private set; }
|
||||
|
||||
[Header("Настройки выдачи призов")]
|
||||
[SerializeField] private bool givePrizes = true;
|
||||
[SerializeField] private bool enableHopper = false;
|
||||
|
||||
[Header("Настройки генерации QR-кодов")]
|
||||
[SerializeField] private List<QRCodeData> qrCodes = new();
|
||||
private readonly List<Texture2D> generatedQRCodes = new();
|
||||
|
||||
[SerializeField] private string _phoneNumberMask = "+7XXXXXXXXXX";
|
||||
// [SerializeField] private string telegramLinkPrefix = "https://t.me/";
|
||||
// [SerializeField] private string whatsappLinkPrefix = "https://wa.me/";
|
||||
|
||||
private string _phoneNumber = string.Empty;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
if (Instance != null && Instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
Instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
|
||||
Debug.Log(givePrizes
|
||||
? "Prize System Initialized: Prizes will be given."
|
||||
: "Prize System Initialized: Prizes will NOT be given.");
|
||||
|
||||
Debug.Log(enableHopper ? "Hopper is enabled for prize dispensing." : "Hopper is disabled.");
|
||||
|
||||
_phoneNumber = SettingsManager.Instance.GetCurrentGameSettings().phoneNumber;
|
||||
_phoneNumber = PhoneNumberUtils.ValidatePhoneNumber(_phoneNumber);
|
||||
_phoneNumber = PhoneNumberUtils.ApplyPhoneMask(_phoneNumber, _phoneNumberMask);
|
||||
|
||||
GenerateQRCodes();
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
// Если не инициализируется в GameManager, инициализировать тут
|
||||
// private void Awake()
|
||||
// {
|
||||
// Initialize();
|
||||
// }
|
||||
|
||||
public void GivePrize()
|
||||
{
|
||||
if (enableHopper)
|
||||
PrizeSystem.GivePrize();
|
||||
else
|
||||
Debug.Log("Hopper is disabled. Prize dispensing skipped.");
|
||||
}
|
||||
|
||||
public Texture2D[] GetQRCodes()
|
||||
{
|
||||
return generatedQRCodes.ToArray();
|
||||
}
|
||||
|
||||
private void GenerateQRCodes()
|
||||
{
|
||||
// Очищаем предыдущие QR-коды
|
||||
if (generatedQRCodes.Count > 0) generatedQRCodes.Clear();
|
||||
|
||||
foreach (QRCodeData data in qrCodes)
|
||||
{
|
||||
if (!data.generateQRCode) continue;
|
||||
string fullLink = data.GetFullLink(_phoneNumber);
|
||||
Texture2D qrTexture = QRMaker.MakeTexture(fullLink);
|
||||
generatedQRCodes.Add(qrTexture);
|
||||
Debug.Log($"Generated QR Code for link: {fullLink}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using RR.Common.UI;
|
||||
using RR.Common.Utility;
|
||||
using RR.Game2D.Core.Managers;
|
||||
using UnityEngine;
|
||||
|
||||
@ -13,9 +14,10 @@ namespace RR.Common.Behaviour.ScriptableObjects
|
||||
public float musicVolume;
|
||||
public float sfxVolume;
|
||||
|
||||
// Payment settings
|
||||
// Payment/prizing settings
|
||||
public bool isFreeGame;
|
||||
public bool isGivingPrizes;
|
||||
public string phoneNumber;
|
||||
|
||||
// Player settings
|
||||
public int startLivesCount;
|
||||
@ -29,6 +31,7 @@ namespace RR.Common.Behaviour.ScriptableObjects
|
||||
|
||||
isFreeGame = false;
|
||||
isGivingPrizes = true;
|
||||
phoneNumber = "9123456789";
|
||||
|
||||
startLivesCount = 3;
|
||||
livesIncreasedByCredits = 1;
|
||||
@ -47,6 +50,8 @@ namespace RR.Common.Behaviour.ScriptableObjects
|
||||
|
||||
if (livesIncreasedByCredits < 0)
|
||||
livesIncreasedByCredits = 0;
|
||||
|
||||
phoneNumber = PhoneNumberUtils.ValidatePhoneNumber(phoneNumber);
|
||||
}
|
||||
|
||||
public void ApplySettings()
|
||||
@ -59,7 +64,6 @@ namespace RR.Common.Behaviour.ScriptableObjects
|
||||
GameManager.Instance.Audio.SetMusicVolume(musicVolume);
|
||||
GameManager.Instance.Audio.SetSfxVolume(sfxVolume);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,6 @@ MonoBehaviour:
|
||||
sfxVolume: 1
|
||||
isFreeGame: 0
|
||||
isGivingPrizes: 1
|
||||
phoneNumber: 9187853714
|
||||
startLivesCount: 3
|
||||
livesIncreasedByCredits: 1
|
||||
setLivesToDefaultAfterFirstLose: 1
|
||||
|
||||
56
Assets/Scripts/UI/QRCodeUIController.cs
Normal file
56
Assets/Scripts/UI/QRCodeUIController.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using RR.Game2D.Core.Managers;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class QRCodeUIController : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Transform content;
|
||||
|
||||
private PrizeSystemManager _prizeSystemManager;
|
||||
private GameObject[] _qrCodes;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_prizeSystemManager = PrizeSystemManager.Instance;
|
||||
|
||||
GameManager.Instance.GameWonEvent += AddQRCodes;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
GameManager.Instance.GameWonEvent -= AddQRCodes;
|
||||
}
|
||||
|
||||
private void AddQRCodes(float _)
|
||||
{
|
||||
if (_qrCodes != null) ClearQRCodes();
|
||||
|
||||
Texture2D[] qrCodesImages = _prizeSystemManager.GetQRCodes();
|
||||
_qrCodes = new GameObject[qrCodesImages.Length];
|
||||
|
||||
for (int i = 0; i < qrCodesImages.Length; i++)
|
||||
{
|
||||
_qrCodes[i] = new GameObject("QRCode_" + i, typeof(RectTransform), typeof(Image));
|
||||
_qrCodes[i].transform.SetParent(content, false);
|
||||
|
||||
Sprite sprite = Sprite.Create(qrCodesImages[i],
|
||||
new Rect(0, 0, qrCodesImages[i].width,
|
||||
qrCodesImages[i].height),
|
||||
new Vector2(0.5f, 0.5f));
|
||||
|
||||
_qrCodes[i].GetComponent<Image>().sprite = sprite;
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearQRCodes()
|
||||
{
|
||||
if (_qrCodes == null) return;
|
||||
|
||||
foreach (GameObject qrCode in _qrCodes)
|
||||
{
|
||||
Destroy(qrCode);
|
||||
}
|
||||
|
||||
_qrCodes = null;
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/UI/QRCodeUIController.cs.meta
Normal file
2
Assets/Scripts/UI/QRCodeUIController.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: daf828422caf7c74db507420de242849
|
||||
85
Assets/Scripts/Utilities/PhoneNumberUtils.cs
Normal file
85
Assets/Scripts/Utilities/PhoneNumberUtils.cs
Normal file
@ -0,0 +1,85 @@
|
||||
using UnityEngine;
|
||||
using static System.String;
|
||||
|
||||
namespace RR.Common.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// Утилитарный класс для работы с номерами телефонов.
|
||||
/// Предоставляет методы для валидации и форматирования телефонных номеров.
|
||||
/// </summary>
|
||||
public static class PhoneNumberUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Валидирует номер телефона и возвращает только цифры без кода страны.
|
||||
/// Поддерживает российские номера, начинающиеся с 7 или 8.
|
||||
/// </summary>
|
||||
/// <param name="number">Исходный номер телефона в любом формате (может содержать пробелы, дефисы и другие символы).</param>
|
||||
/// <returns>
|
||||
/// Строка из 10 цифр, представляющая номер без кода страны.
|
||||
/// Возвращает пустую строку, если формат номера неверный.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// Принимаемые форматы:
|
||||
/// - 11 цифр, начинающиеся с 7 или 8 (например, 89001234567 или 79001234567)
|
||||
/// - 10 цифр без кода страны (например, 9001234567)
|
||||
/// При неверном формате выводится предупреждение в консоль Unity.
|
||||
/// </remarks>
|
||||
public static string ValidatePhoneNumber(string number)
|
||||
{
|
||||
// Оставляем только цифры
|
||||
string digitsOnly = System.Text.RegularExpressions.Regex.Replace(number, @"\D", "");
|
||||
|
||||
// Проверяем формат
|
||||
if ((digitsOnly.StartsWith("8") || digitsOnly.StartsWith("7")) && digitsOnly.Length == 11)
|
||||
{
|
||||
return digitsOnly[1..];
|
||||
}
|
||||
else if (digitsOnly.Length == 10)
|
||||
{
|
||||
return digitsOnly;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Неверный формат, возвращаем номер по умолчанию
|
||||
Debug.LogWarning($"Неверный формат номера телефона: {number}. Заменяю на номер по умолчанию.");
|
||||
return Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Применяет маску форматирования к номеру телефона.
|
||||
/// </summary>
|
||||
/// <param name="number">Номер телефона для форматирования.</param>
|
||||
/// <param name="mask">Маска форматирования. По умолчанию "+7XXXXXXXXXX".</param>
|
||||
/// <param name="maskPlaceholder">Символ-заполнитель в маске, который будет заменен на цифры. По умолчанию 'X'.</param>
|
||||
/// <returns>
|
||||
/// Отформатированный номер телефона согласно маске.
|
||||
/// Если номер невалиден, возвращается пустая строка.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// Метод сначала валидирует номер с помощью ValidatePhoneNumber, затем применяет маску.
|
||||
/// Символы маски, не являющиеся заполнителями, остаются без изменений.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// ApplyPhoneMask("89001234567", "+7 (XXX) XXX-XX-XX") вернет "+7 (900) 123-45-67"
|
||||
/// </example>
|
||||
public static string ApplyPhoneMask(string number, string mask = "+7XXXXXXXXXX", char maskPlaceholder = 'X')
|
||||
{
|
||||
string digitsOnly = ValidatePhoneNumber(number);
|
||||
if (IsNullOrEmpty(digitsOnly))
|
||||
return Empty;
|
||||
|
||||
char[] maskedNumber = mask.ToCharArray();
|
||||
int digitIndex = 0;
|
||||
|
||||
for (int i = 0; i < maskedNumber.Length; i++)
|
||||
{
|
||||
if (maskedNumber[i] != maskPlaceholder || digitIndex >= digitsOnly.Length) continue;
|
||||
maskedNumber[i] = digitsOnly[digitIndex];
|
||||
digitIndex++;
|
||||
}
|
||||
|
||||
return new string(maskedNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Utilities/PhoneNumberUtils.cs.meta
Normal file
3
Assets/Scripts/Utilities/PhoneNumberUtils.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9e654e8fac614d7a8b2f5fd06e51792f
|
||||
timeCreated: 1763113002
|
||||
7
Assets/Scripts/Utilities/QRCodeTest.cs
Normal file
7
Assets/Scripts/Utilities/QRCodeTest.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace RR.Common.Utility
|
||||
{
|
||||
public class QRCodeTest
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Utilities/QRCodeTest.cs.meta
Normal file
3
Assets/Scripts/Utilities/QRCodeTest.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 22feb19078804d8e83f3739276b1d8c8
|
||||
timeCreated: 1763126902
|
||||
98
Assets/Scripts/Utilities/QRCodeUtils.cs
Normal file
98
Assets/Scripts/Utilities/QRCodeUtils.cs
Normal file
@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using QRCoder;
|
||||
using UnityEngine;
|
||||
using Color = System.Drawing.Color;
|
||||
|
||||
namespace RR.Common.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// Утилитарный класс для создания QR-кодов в Unity.
|
||||
/// Предоставляет статические методы для генерации QR-кодов в виде текстур.
|
||||
/// </summary>
|
||||
public class QRMaker : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Создает текстуру QR-кода из переданного текста.
|
||||
/// </summary>
|
||||
/// <param name="text">Текст или данные для кодирования в QR-код.</param>
|
||||
/// <param name="pixelsPerModule">Количество пикселей на один модуль QR-кода. По умолчанию 8.</param>
|
||||
/// <param name="drawQuietZones">Определяет, нужно ли рисовать тихие зоны (белые поля) вокруг QR-кода. По умолчанию true.</param>
|
||||
/// <returns>Texture2D с изображением QR-кода, готовая для использования в UI или материалах.</returns>
|
||||
public static Texture2D MakeTexture(string text, int pixelsPerModule = 8,
|
||||
bool drawQuietZones = true)
|
||||
{
|
||||
QRCodeGenerator gen = new();
|
||||
QRCoder.QRCodeData data = gen.CreateQrCode(text, QRCodeGenerator.ECCLevel.M);
|
||||
|
||||
PngByteQRCode png = new(data);
|
||||
|
||||
// Генерим PNG-байты без System.Drawing
|
||||
byte[] bytes = png.GetGraphic(pixelsPerModule);
|
||||
|
||||
Texture2D tex = new(150, 150, TextureFormat.RGBA32, false);
|
||||
tex.LoadImage(bytes); // раскодирует PNG → RGBA
|
||||
tex.Apply(false, false);
|
||||
return tex;
|
||||
}
|
||||
|
||||
// public static Texture2D MakeTexture(string text, Image icon = null, int pixelsPerModule = 8,
|
||||
// bool drawQuietZones = true)
|
||||
// {
|
||||
// QRCodeGenerator gen = new();
|
||||
// QRCoder.QRCodeData data = gen.CreateQrCode(text, QRCodeGenerator.ECCLevel.M);
|
||||
// QRCode code = new(data);
|
||||
// Bitmap bitmapIcon = code.GetGraphic(pixelsPerModule,
|
||||
// Color.Black,
|
||||
// Color.White,
|
||||
// icon == null ? null : new Bitmap(icon),
|
||||
// 15,
|
||||
// 10,
|
||||
// drawQuietZones);
|
||||
// Texture2D tex = new(150, 150, TextureFormat.RGBA32, false);
|
||||
// tex.LoadImage(bitmapIcon);
|
||||
// }
|
||||
|
||||
// Сохранить как PNG-файл
|
||||
public static string SavePng(string text, string filePath, int ppm = 8)
|
||||
{
|
||||
QRCodeGenerator gen = new();
|
||||
QRCoder.QRCodeData data = gen.CreateQrCode(text, QRCodeGenerator.ECCLevel.M);
|
||||
PngByteQRCode png = new PngByteQRCode(data);
|
||||
byte[] bytes = png.GetGraphic(ppm, Color.Black, Color.White, true);
|
||||
File.WriteAllBytes(filePath, bytes);
|
||||
return filePath;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Структура данных для конфигурации генерации QR-кода.
|
||||
/// Содержит параметры для создания полных ссылок с префиксом и суффиксом.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public struct QRCodeData
|
||||
{
|
||||
/// <summary>
|
||||
/// Флаг, определяющий, нужно ли генерировать QR-код.
|
||||
/// </summary>
|
||||
public bool generateQRCode;
|
||||
/// <summary>
|
||||
/// Префикс ссылки (например, "https://example.com/").
|
||||
/// </summary>
|
||||
public string linkPrefix;
|
||||
/// <summary>
|
||||
/// Суффикс, добавляемый в качестве параметра запроса.
|
||||
/// </summary>
|
||||
public string suffix;
|
||||
|
||||
/// <summary>
|
||||
/// Формирует полную ссылку, объединяя префикс, данные и суффикс.
|
||||
/// </summary>
|
||||
/// <param name="data">Основные данные для включения в ссылку.</param>
|
||||
/// <returns>Полная ссылка в формате: {linkPrefix}{data}?text={suffix}</returns>
|
||||
public string GetFullLink(string data) => $"{linkPrefix}{data}?text={ProcessSuffix(suffix)}";
|
||||
|
||||
private string ProcessSuffix(string rawSuffix) => Uri.EscapeDataString(rawSuffix);
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Utilities/QRCodeUtils.cs.meta
Normal file
3
Assets/Scripts/Utilities/QRCodeUtils.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6cd7d86305114f21b64b8ef43acbdf7f
|
||||
timeCreated: 1763113697
|
||||
Loading…
x
Reference in New Issue
Block a user