Revert "calling scene final done plus updates"

This reverts commit 6fded2c20d.
This commit is contained in:
Mark Joshwel 2025-02-11 14:53:53 +08:00
parent 46330c0ab2
commit 8b2ebe21e3
101 changed files with 347858 additions and 98934 deletions

View file

@ -17,6 +17,7 @@ public class Car : MonoBehaviour
public float rotationSpeed = 5.0f; // Smooth turning speed
private int currentWaypointIndex = 0; // Starting at the first waypoint
public Vector3 rotationOffset = Vector3.zero;
private void OnTriggerEnter(Collider other)
{
Debug.Log("Triggered by: " + other.name);
@ -64,7 +65,8 @@ public class Car : MonoBehaviour
if (direction != Vector3.zero)
{
Quaternion lookRotation = Quaternion.LookRotation(direction);
// Apply rotation offset
Quaternion lookRotation = Quaternion.LookRotation(direction) * Quaternion.Euler(rotationOffset);
transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, rotationSpeed * Time.deltaTime);
}
}

View file

@ -12,7 +12,6 @@ dependencies {
implementation 'com.google.firebase:firebase-common:21.0.0' // Assets/Firebase/Editor/AppDependencies.xml:13
implementation 'com.google.firebase:firebase-database:21.0.0' // Assets/Firebase/Editor/DatabaseDependencies.xml:13
implementation 'com.google.firebase:firebase-database-unity:12.5.0' // Assets/Firebase/Editor/DatabaseDependencies.xml:22
implementation 'com.unity3d.ads:unity-ads:[4.12.0,4.13[' // Packages/com.unity.ads/Editor/Source/Dependencies.xml:7
// Android Resolver Dependencies End
**DEPS**}

View file

@ -21,9 +21,6 @@ dependencyResolutionManagement {
maven {
url (unityProjectPath + "/Assets/GeneratedLocalRepo/Firebase/m2repository") // Assets/Firebase/Editor/AppDependencies.xml:22, Assets/Firebase/Editor/AuthDependencies.xml:20, Assets/Firebase/Editor/DatabaseDependencies.xml:22
}
maven {
url "https://maven.google.com/" // Packages/com.unity.ads/Editor/Source/Dependencies.xml:7
}
mavenLocal()
// Android Resolver Repos End
flatDir {

View file

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: a683a25bdfe6a476489d2d3d4b273e5a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -1,109 +0,0 @@
fileFormatVersion: 2
guid: c561d7bb9e03246749196b85fa1f0a9a
ModelImporter:
serializedVersion: 22200
internalIDToNameTable: []
externalObjects: {}
materials:
materialImportMode: 2
materialName: 0
materialSearch: 1
materialLocation: 1
animations:
legacyGenerateAnimations: 4
bakeSimulation: 0
resampleCurves: 1
optimizeGameObjects: 0
removeConstantScaleCurves: 0
motionNodeName:
rigImportErrors:
rigImportWarnings:
animationImportErrors:
animationImportWarnings:
animationRetargetingWarnings:
animationDoRetargetingWarnings: 0
importAnimatedCustomProperties: 0
importConstraints: 0
animationCompression: 1
animationRotationError: 0.5
animationPositionError: 0.5
animationScaleError: 0.5
animationWrapMode: 0
extraExposedTransformPaths: []
extraUserProperties: []
clipAnimations: []
isReadable: 0
meshes:
lODScreenPercentages: []
globalScale: 1
meshCompression: 0
addColliders: 0
useSRGBMaterialColor: 1
sortHierarchyByName: 1
importPhysicalCameras: 1
importVisibility: 1
importBlendShapes: 1
importCameras: 1
importLights: 1
nodeNameCollisionStrategy: 1
fileIdsGeneration: 2
swapUVChannels: 0
generateSecondaryUV: 0
useFileUnits: 1
keepQuads: 0
weldVertices: 1
bakeAxisConversion: 0
preserveHierarchy: 0
skinWeightsMode: 0
maxBonesPerVertex: 4
minBoneWeight: 0.001
optimizeBones: 1
meshOptimizationFlags: -1
indexFormat: 0
secondaryUVAngleDistortion: 8
secondaryUVAreaDistortion: 15.000001
secondaryUVHardAngle: 88
secondaryUVMarginMethod: 1
secondaryUVMinLightmapResolution: 40
secondaryUVMinObjectScale: 1
secondaryUVPackMargin: 4
useFileScale: 1
strictVertexDataChecks: 0
tangentSpace:
normalSmoothAngle: 60
normalImportMode: 0
tangentImportMode: 3
normalCalculationMode: 4
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
blendShapeNormalImportMode: 1
normalSmoothingSource: 0
referencedClips: []
importAnimation: 1
humanDescription:
serializedVersion: 3
human: []
skeleton: []
armTwist: 0.5
foreArmTwist: 0.5
upperLegTwist: 0.5
legTwist: 0.5
armStretch: 0.05
legStretch: 0.05
feetSpacing: 0
globalScale: 1
rootMotionBoneName:
hasTranslationDoF: 0
hasExtraRoot: 0
skeletonHasParents: 1
lastHumanDescriptionAvatarSource: {instanceID: 0}
autoGenerateAvatarMappingIfUnspecified: 1
animationType: 2
humanoidOversampling: 1
avatarSetup: 0
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
importBlendShapeDeformPercent: 1
remapMaterialsIfMaterialImportModeIsNone: 0
additionalBone: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,285 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &912096211955130279
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2013033037160586228}
- component: {fileID: 8261849051462643620}
- component: {fileID: 759604744662927459}
m_Layer: 0
m_Name: antM_low
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &2013033037160586228
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 912096211955130279}
serializedVersion: 2
m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067}
m_LocalPosition: {x: -0, y: 9.28421, z: -2.0345063}
m_LocalScale: {x: 100, y: 100, z: 100}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4915882180731493894}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &8261849051462643620
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 912096211955130279}
m_Mesh: {fileID: -8541198254713435205, guid: c561d7bb9e03246749196b85fa1f0a9a, type: 3}
--- !u!23 &759604744662927459
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 912096211955130279}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: -8875217895517861824, guid: c561d7bb9e03246749196b85fa1f0a9a, type: 3}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!1 &1768235561626958404
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4915882180731493894}
m_Layer: 0
m_Name: BrickPhoneLowDownload
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4915882180731493894
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1768235561626958404}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068}
m_LocalPosition: {x: 70.804, y: 20.837, z: 1067.862}
m_LocalScale: {x: 0.019977802, y: 0.019977802, z: 0.019977802}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 2013033037160586228}
- {fileID: 4616873687985266841}
- {fileID: 7804254000881719757}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0}
--- !u!1 &4420913256116487916
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7804254000881719757}
- component: {fileID: 3433484275228039231}
- component: {fileID: 6356307892325067043}
m_Layer: 0
m_Name: mainM_low
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &7804254000881719757
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4420913256116487916}
serializedVersion: 2
m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067}
m_LocalPosition: {x: -0, y: 0, z: 0}
m_LocalScale: {x: 100, y: 100, z: 100}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4915882180731493894}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &3433484275228039231
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4420913256116487916}
m_Mesh: {fileID: 9077211823755307291, guid: c561d7bb9e03246749196b85fa1f0a9a, type: 3}
--- !u!23 &6356307892325067043
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4420913256116487916}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: -8875217895517861824, guid: c561d7bb9e03246749196b85fa1f0a9a, type: 3}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!1 &5972010611662714101
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4616873687985266841}
- component: {fileID: 2684504323854613876}
- component: {fileID: 5686608003106059253}
m_Layer: 0
m_Name: buttonM_low
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4616873687985266841
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5972010611662714101}
serializedVersion: 2
m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067}
m_LocalPosition: {x: -0, y: -0.43995914, z: -0.14976536}
m_LocalScale: {x: 100, y: 100, z: 100}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4915882180731493894}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &2684504323854613876
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5972010611662714101}
m_Mesh: {fileID: 2462693897657455071, guid: c561d7bb9e03246749196b85fa1f0a9a, type: 3}
--- !u!23 &5686608003106059253
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5972010611662714101}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: -8875217895517861824, guid: c561d7bb9e03246749196b85fa1f0a9a, type: 3}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}

View file

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: f3bec1a93d9784b08b1935cee51f970d
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,127 +0,0 @@
fileFormatVersion: 2
guid: 448349a0c94b34f6fa5ed8f81154ec0d
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,127 +0,0 @@
fileFormatVersion: 2
guid: 47b6bd24bc2654c0e99ae307204ffc71
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,127 +0,0 @@
fileFormatVersion: 2
guid: cc2e5b8448a2a487db92fd0736ee867a
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 1
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,127 +0,0 @@
fileFormatVersion: 2
guid: 69e860b17782e4f7abe53574f83754cf
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,136 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: phone
m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords:
- _METALLICSPECGLOSSMAP
- _NORMALMAP
- _OCCLUSIONMAP
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap:
RenderType: Opaque
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BaseMap:
m_Texture: {fileID: 2800000, guid: 448349a0c94b34f6fa5ed8f81154ec0d, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:
m_Texture: {fileID: 2800000, guid: cc2e5b8448a2a487db92fd0736ee867a, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: 448349a0c94b34f6fa5ed8f81154ec0d, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 2800000, guid: 69e860b17782e4f7abe53574f83754cf, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 2800000, guid: 47b6bd24bc2654c0e99ae307204ffc71, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SpecGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_Lightmaps:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_LightmapsInd:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_ShadowMasks:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _AlphaClip: 0
- _AlphaToMask: 0
- _Blend: 0
- _BlendModePreserveSpecular: 1
- _BumpScale: 1
- _ClearCoatMask: 0
- _ClearCoatSmoothness: 0
- _Cull: 2
- _Cutoff: 0.5
- _DetailAlbedoMapScale: 1
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _DstBlendAlpha: 0
- _EnvironmentReflections: 1
- _GlossMapScale: 0
- _Glossiness: 0
- _GlossyReflections: 0
- _Metallic: 0
- _OcclusionStrength: 1
- _Parallax: 0.005
- _QueueOffset: 0
- _ReceiveShadows: 1
- _Smoothness: 0.5
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _SrcBlendAlpha: 1
- _Surface: 0
- _WorkflowMode: 1
- _ZWrite: 1
m_Colors:
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
m_BuildTextureStacks: []
--- !u!114 &5455462648426782637
MonoBehaviour:
m_ObjectHideFlags: 11
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
m_Name:
m_EditorClassIdentifier:
version: 7

View file

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 2cdabdeb3f27643aca59671232096b74
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View file

@ -3547,7 +3547,7 @@ Transform:
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 76.483, y: 20.062338, z: 1074.189}
m_LocalScale: {x: 0.71024, y: 1, z: 1}
m_LocalScale: {x: 1.4272895, y: 1.6624316, z: 1.2563}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1042055672864314654}
@ -6213,7 +6213,7 @@ MeshCollider:
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 5
m_Convex: 0
m_Convex: 1
m_CookingOptions: 30
m_Mesh: {fileID: 0}
--- !u!1 &8310460265778558687

View file

@ -1064,7 +1064,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 763
m_VersionIndex: 766
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []
@ -2236,7 +2236,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 763
m_VersionIndex: 766
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []
@ -3408,7 +3408,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 763
m_VersionIndex: 766
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []
@ -4580,7 +4580,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 763
m_VersionIndex: 766
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []
@ -4719,7 +4719,7 @@ Transform:
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 76.483, y: 20.062338, z: 1075.977}
m_LocalScale: {x: 0.71024, y: 1, z: 1}
m_LocalScale: {x: 1.427289, y: 1.662432, z: 1.2563}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1079596460906746210}
@ -7281,7 +7281,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 4304
m_VersionIndex: 4307
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []
@ -7385,6 +7385,6 @@ MeshCollider:
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 5
m_Convex: 0
m_Convex: 1
m_CookingOptions: 30
m_Mesh: {fileID: 0}

View file

@ -31,7 +31,7 @@ Transform:
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 76.483, y: 20.062338, z: 1078.15}
m_LocalScale: {x: 0.71024, y: 1, z: 1}
m_LocalScale: {x: 1.427289, y: 1.662432, z: 1.2563}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 5371903328586580264}
@ -2593,7 +2593,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 4310
m_VersionIndex: 4313
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []
@ -2697,7 +2697,7 @@ MeshCollider:
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 5
m_Convex: 0
m_Convex: 1
m_CookingOptions: 30
m_Mesh: {fileID: 0}
--- !u!1 &4688572630381258159
@ -3764,7 +3764,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 766
m_VersionIndex: 769
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []
@ -4936,7 +4936,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 766
m_VersionIndex: 769
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []
@ -6108,7 +6108,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 766
m_VersionIndex: 769
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []
@ -7280,7 +7280,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 766
m_VersionIndex: 769
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []

View file

@ -1064,7 +1064,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 760
m_VersionIndex: 763
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []
@ -2236,7 +2236,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 760
m_VersionIndex: 763
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []
@ -3408,7 +3408,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 760
m_VersionIndex: 763
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []
@ -3547,7 +3547,7 @@ Transform:
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 76.483, y: 20.062338, z: 1071.428}
m_LocalScale: {x: 0.71024, y: 1, z: 1}
m_LocalScale: {x: 1.427289, y: 1.662432, z: 1.2563}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7593893600841095933}
@ -6109,7 +6109,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 4301
m_VersionIndex: 4304
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []
@ -6213,7 +6213,7 @@ MeshCollider:
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 5
m_Convex: 0
m_Convex: 1
m_CookingOptions: 30
m_Mesh: {fileID: 0}
--- !u!1 &6269964064440433305
@ -7280,7 +7280,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 760
m_VersionIndex: 763
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []

View file

@ -1064,7 +1064,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 763
m_VersionIndex: 766
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []
@ -1186,6 +1186,7 @@ GameObject:
- component: {fileID: 2945161744182452091}
- component: {fileID: 3378180745088993557}
- component: {fileID: 1197120804817647912}
- component: {fileID: 924488159461366713}
m_Layer: 0
m_Name: WhiteCar_Reza
m_TagString: Untagged
@ -1203,7 +1204,7 @@ Transform:
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 76.483, y: 20.062338, z: 1080.34}
m_LocalScale: {x: 0.71024, y: 1, z: 1}
m_LocalScale: {x: 1.427289, y: 1.662432, z: 1.2563}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 6702699104838786083}
@ -3765,7 +3766,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 4307
m_VersionIndex: 4310
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []
@ -3869,9 +3870,26 @@ MeshCollider:
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 5
m_Convex: 0
m_Convex: 1
m_CookingOptions: 30
m_Mesh: {fileID: 0}
--- !u!114 &924488159461366713
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1884055412810011501}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 068fbcec103081147a0588ec72e53ee0, type: 3}
m_Name:
m_EditorClassIdentifier:
playerRig: {fileID: 0}
startPoint: {fileID: 0}
waypoints: []
speed: 3
rotationSpeed: 5
--- !u!1 &2813551867002969041
GameObject:
m_ObjectHideFlags: 0
@ -4936,7 +4954,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 763
m_VersionIndex: 766
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []
@ -6108,7 +6126,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 763
m_VersionIndex: 766
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []
@ -7280,7 +7298,7 @@ MonoBehaviour:
m_PreserveMeshAssetOnDestroy: 0
assetGuid:
m_Mesh: {fileID: 0}
m_VersionIndex: 763
m_VersionIndex: 766
m_IsSelectable: 1
m_SelectedFaces:
m_SelectedEdges: []

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: c28d17a3f5d8946a6aff3f8bc5f9b5b0
guid: 48cde6b0ab9794ada98c7371a0e98e40
DefaultImporter:
externalObjects: {}
userData:

File diff suppressed because one or more lines are too long

View file

@ -1,62 +0,0 @@
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine.SceneManagement;
using UnityEngine.XR.Interaction.Toolkit.Interactors;
public class PhoneInteraction : MonoBehaviour
{
public AudioClip phoneCallAudio; // Assign in Inspector
public GameObject choiceUI; // Assign your UI Panel in Inspector
private AudioSource audioSource;
private bool phonePickedUp = false;
private bool choiceMade = false;
void Start()
{
audioSource = GetComponent<AudioSource>() ?? gameObject.AddComponent<AudioSource>();
audioSource.clip = phoneCallAudio;
choiceUI.SetActive(false); // Hide UI initially
}
void Update()
{
if (phonePickedUp && !choiceMade)
{
if (Input.GetKeyDown(KeyCode.G))
{
AnswerCall();
}
else if (Input.GetKeyDown(KeyCode.B))
{
DeclineCall();
}
}
}
public void PickUpPhone()
{
if (!phonePickedUp)
{
phonePickedUp = true;
Debug.Log("Phone Picked Up! UI Appears.");
choiceUI.SetActive(true); // Show UI when picked up
}
}
void AnswerCall()
{
choiceMade = true;
Debug.Log("Phone Answered! Playing Audio...");
audioSource.Play();
choiceUI.SetActive(false); // Hide UI after choice
}
void DeclineCall()
{
choiceMade = true;
Debug.Log("Call Declined! Loading 'House' scene...");
SceneManager.LoadScene("House");
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 8b0dfcf36d5ac40258ab35afd9619120
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -8,7 +8,6 @@
<package>com.google.firebase:firebase-common:21.0.0</package>
<package>com.google.firebase:firebase-database:21.0.0</package>
<package>com.google.firebase:firebase-database-unity:12.5.0</package>
<package>com.unity3d.ads:unity-ads:[4.12.0,4.13[</package>
</packages>
<files>
<file>Assets/GeneratedLocalRepo/Firebase/m2repository/com/google/firebase/firebase-app-unity/12.5.0/firebase-app-unity-12.5.0.aar</file>

View file

@ -8,7 +8,7 @@ EditorBuildSettings:
- enabled: 1
path: Assets/Samples/XR Interaction Toolkit/3.0.3/Scenes/SampleScene.unity
guid: 55daccc09a3b69647bbab145b54a3ab3
- enabled: 0
- enabled: 1
path: Assets/Scenes/calling scene.unity
guid: 48cde6b0ab9794ada98c7371a0e98e40
- enabled: 1

View file

@ -9,7 +9,7 @@
{
"type": "UnityEngine.ProBuilder.SelectMode, Unity.ProBuilder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
"key": "editor.lastMeshSelectMode",
"value": "{\"m_Value\":8}"
"value": "{\"m_Value\":2}"
},
{
"type": "System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
@ -111,11 +111,6 @@
"key": "editor.stripProBuilderScriptsOnBuild",
"value": "{\"m_Value\":true}"
},
{
"type": "System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"key": "editor.extrudeEdgesAsGroup",
"value": "{\"m_Value\":true}"
},
{
"type": "UnityEngine.ProBuilder.SelectionModifierBehavior, Unity.ProBuilder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
"key": "editor.rectSelectModifier",
@ -159,18 +154,13 @@
{
"type": "System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"key": "ShapeBuilder.ActiveShapeIndex",
"value": "{\"m_Value\":6}"
"value": "{\"m_Value\":7}"
},
{
"type": "System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"key": "ShapeBuilder.LastPivotLocation",
"value": "{\"m_Value\":1}"
},
{
"type": "System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"key": "SubdivideEdges.subdivisions",
"value": "{\"m_Value\":1}"
},
{
"type": "UnityEngine.ProBuilder.PivotLocation, Unity.ProBuilder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
"key": "mesh.newShapePivotLocation",
@ -184,11 +174,7 @@
{
"type": "UnityEngine.Vector3, UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
"key": "ShapeBuilder.LastSize",
<<<<<<< HEAD
"value": "{\"m_Value\":{\"x\":-0.4071826934814453,\"y\":0.2012939453125,\"z\":-0.5807037353515625}}"
=======
"value": "{\"m_Value\":{\"x\":0.197540283203125,\"y\":0.015741348266601564,\"z\":0.1954345703125}}"
>>>>>>> fb51f41 (calling updates)
"value": "{\"m_Value\":{\"x\":0.248779296875,\"y\":-0.09796714782714844,\"z\":0.2877197265625}}"
},
{
"type": "UnityEngine.Quaternion, UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
@ -264,11 +250,6 @@
"type": "System.Single, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"key": "uv.uvEditorGridSnapIncrement",
"value": "{\"m_Value\":0.125}"
},
{
"type": "System.Single, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"key": "ExtrudeEdges.distance",
"value": "{\"m_Value\":0.5}"
}
]
}

5
OldWeb/.firebaserc Normal file
View file

@ -0,0 +1,5 @@
{
"projects": {
"default": "echoesbehindcloseddoors"
}
}

144
OldWeb/.gitignore vendored Normal file
View file

@ -0,0 +1,144 @@
# Logs
logs
_.log
*.log
npm-debug.log_
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
_.pid
_.seed
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# vitepress build output
**/.vitepress/dist
# vitepress cache directory
**/.vitepress/cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
# firebase cache?
.firebase/*.cache

130
OldWeb/README.md Normal file
View file

@ -0,0 +1,130 @@
# The 'Echoes Behind Closed Doors' Website (and Game Backend Documentation)
for the Developing Dyamic Applications module as part of the Year 2.2
Integrated Project for Ngee Ann Polytechnic's Diploma in Immersive Media
## Game, Stack, and Data Model
### Gameplay
the game is a vr experience not too dissimilar to storytelling-heavy
experiences like visual novels but with a few gameplay mechanics, making it
similar to games like Firewatch
current storyline/gameplay description:
> A teen is experiencing a spiral of mental health challenges exacerbated by
> domestic violence. Players navigate their world through simple, interactive
> daily tasks, which slowly reveal the layers of the teens struggles. The
> narrative emphasizes realism, empathy, and awareness.
### Stack and Usage
##### Stack
- **Firebase Auth:** for authentication
- **Firebase Realtime Database:** for player data
- **Firebase Hosting:** for hosting the website
- **Supabase Storage:** for storing the recorded messages
##### Usage Flow
because we also are presenting this via a booth-based viva voce demonstration,
we are pretending as if we are the partner Ngee Ann companies that will
presumably be at the booth, and as such this website is more for the booth
runners than the players themselves
TODO
1. **Booth Laptop:** show a registration qr code (firebase hosting)
2. **Players Personal Device:** make an account (firebase auth)
3. **Players Personal Device:** post-sign up, they are innocently asked to
"record a message for someone with mental health struggles"
(stored via supabase storage)
4. **Booth Laptop:** booth runner via a dashboard sets the user as the
"currently playing user" (firebase realtime database)
5. **Meta Quest:** player plays the game, the game using the UID of the
"currently playing user" to record the players choices
(firebase realtime database)
6. **Meta Quest:** at the crux of the game, the call from the player's 'friend' is
actually the recorded message from the booth laptop
1. fetch url from firebase realtime database
2. download from supabase storage
3. play in-game via unity
7. **Meta Quest:** finish game, ending is recorded in firebase realtime database
8. **Booth Laptop/Players Personal Device:** can see the player's choices and ending via their profile page
- players can send their profile page to their friends to show if they want to,
i'll probably this via url parameters (e.g. `profile.html?uid=...`) like the
last group project i was in because we're not using any fancy frontend
frameworks (firebase hosting)
9. **Booth Laptop:** via the same dashboard is able to see:
- the current players' real-time progress
- all past players
- their emails
- and profile pages
- maybe some global statistics if there's time
### Data Model
(for firebase realtime database)
```text
currentUser: <uid>
plays
└── <playId>
├── uid: <uid>
├── day1
│ ├── brushTeeth: true
│ └── ...
├── day2
│ └── ...
└── finalday
├── acceptCall: true
└── ...
user
└── <userid>/
└── callUrl: <supabase storage link>
```
## Development Setup
### Local Development Setup
[bun](https://bun.sh/) is used as the package manager and bundler for this project,
but npm can be used as well for tailwindcss
**note:** firebase-tools does not work well with bun,
so you will need to use npm for that
everything you need to do is available as a script in the `package.json` file
use `bun run ...` or `npm run ...` to run the scripts
| script | description | bun | npm |
|--------|-------------|-----|-----|
| `css` | build css from tailwind | ✅ | ✅ |
| `build` | buiild css and bundle the website | ✅ | ❌ |
| `dev-css` | build css and watch | ✅ | ✅ |
| `dev-build` | bundle and watch (this does not watch build css on filesystem change, please run `dev-css` separately) | ✅ | ❌ |
| `deploy-live` | deploy to firebase hosting | ✅ | ✅ |
| `deploy-staging` | deploy to firebase hosting on a staging channel | ✅ | ✅ |
| `deploy` | `build` + `deploy-live` | ✅ | ❌ |
### Cloud Development Setup
- Firebase Project
- Authentication
- Email/Password Provider
- Email/Password: enabled
- Email link (passwordless sign-in): enabled
- Realtime Database
- Security Rules: (TODO; if i have time to define them before submission)
- Hosting \
(not strictly necessary)
- Supabase Project
- Storage
- Bucket
- named it `telephonies` but like i don't think it matters
- Enable connection via S3 protocol: enabled (TODO; might not even use this way of uploading)
- Policies: (TODO; if i have time to define them before submission)

File diff suppressed because one or more lines are too long

2
OldWeb/css/styles.min.css vendored Normal file

File diff suppressed because one or more lines are too long

10
OldWeb/firebase-config.js Normal file
View file

@ -0,0 +1,10 @@
export const firebaseConfig = {
apiKey: "AIzaSyARm-eSymd2Q3AyxJXiAiiUzsXGmc6T72I",
authDomain: "echoesbehindcloseddoors.firebaseapp.com",
databaseURL:
"https://echoesbehindcloseddoors-default-rtdb.asia-southeast1.firebasedatabase.app",
projectId: "echoesbehindcloseddoors",
storageBucket: "echoesbehindcloseddoors.firebasestorage.app",
messagingSenderId: "905742343227",
appId: "1:905742343227:web:19d04f77371ef1952c901e",
};

10
OldWeb/firebase.json Normal file
View file

@ -0,0 +1,10 @@
{
"hosting": {
"public": "public",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
}

View file

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -153,21 +153,21 @@
<div data-uk-dropdown="mode: click">
<ul class="uk-dropdown-nav uk-nav">
<li id="nav-auth-logIn">
<a href="/login">Log In</a>
<a href="/auth.html">Log In</a>
</li>
<li id="nav-auth-signUp">
<a href="/signup">Sign Up</a>
<a href="/auth.html">Sign Up</a>
</li>
<li id="nav-auth-logOut">
<a href="/profile?logOut=true">Log Out</a>
<a href="/profile.html?logOut=true">Log Out</a>
</li>
<li id="nav-auth-profile">
<a href="/profile">Profile</a>
<a href="/profile.html">Profile</a>
</li>
</ul>
</div>
</li>
<li><a href="/booth">Manage Booth</a></li>
<li><a href="/booth.html">Manage Booth</a></li>
</ul>
</nav>
</header>

0
OldWeb/js/auth.js Normal file
View file

View file

@ -29,7 +29,7 @@
<!-- TODO: social share -->
<!-- franken-ui -->
<link rel="stylesheet" href="/css/styles.css" />
<link rel="stylesheet" href="/css/styles.min.css" />
<script
type="module"
src="/js/franken-ui.js"

View file

@ -2,8 +2,8 @@
"name": "echoesbehindcloseddoors-web",
"scripts": {
"css": "tailwindcss -i css/styles.src.css -o css/styles.css --minify",
"css-process": "lightningcss --minify --bundle css/styles.css -o css/styles.min.css",
"build": "bun run css && bun run css-process && rm -rf public/; bun build index.html --outdir=public",
"css-process": "lightningcss --minify --bundle --targets '>= 0.25%' css/styles.css -o css/styles.min.css",
"build": "bun run css && bun run css-process && rm -rf public/; bun build index.html login.html --outdir=public",
"dev-css": "tailwindcss -i css/styles.src.css -o css/styles.css --watch",
"dev-build": "bun build index.html --outdir=public --watch",
"deploy-live": "firebase deploy --only hosting",

View file

@ -90,25 +90,15 @@ user
### Local Development Setup
[bun](https://bun.sh/) is used as the package manager and bundler for this project,
but npm can be used as well for tailwindcss
~~[bun](https://bun.sh/) is used as the package manager and bundler for this project,
but npm can be used as well for tailwindcss~~
**note:** firebase-tools does not work well with bun,
so you will need to use npm for that
~~**note:** firebase-tools does not work well with bun,
so you will need to use npm for that~~
everything you need to do is available as a script in the `package.json` file
use a live server, firebase emulator, or something similar
use `bun run ...` or `npm run ...` to run the scripts
| script | description | bun | npm |
|--------|-------------|-----|-----|
| `css` | build css from tailwind | ✅ | ✅ |
| `build` | buiild css and bundle the website | ✅ | ❌ |
| `dev-css` | build css and watch | ✅ | ✅ |
| `dev-build` | bundle and watch (this does not watch build css on filesystem change, please run `dev-css` separately) | ✅ | ❌ |
| `deploy-live` | deploy to firebase hosting | ✅ | ✅ |
| `deploy-staging` | deploy to firebase hosting on a staging channel | ✅ | ✅ |
| `deploy` | `build` + `deploy-live` | ✅ | ❌ |
everything is in the `public/` folder, and works as-is
### Cloud Development Setup

File diff suppressed because one or more lines are too long

View file

@ -1,9 +1,10 @@
export const firebaseConfig = {
apiKey: "AIzaSyARm-eSymd2Q3AyxJXiAiiUzsXGmc6T72I",
authDomain: "echoesbehindcloseddoors.firebaseapp.com",
databaseURL: "https://echoesbehindcloseddoors-default-rtdb.asia-southeast1.firebasedatabase.app",
databaseURL:
"https://echoesbehindcloseddoors-default-rtdb.asia-southeast1.firebasedatabase.app",
projectId: "echoesbehindcloseddoors",
storageBucket: "echoesbehindcloseddoors.firebasestorage.app",
messagingSenderId: "905742343227",
appId: "1:905742343227:web:19d04f77371ef1952c901e"
appId: "1:905742343227:web:19d04f77371ef1952c901e",
};

11
Web/public/404.html Normal file
View file

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
404
</body>
</html>

View file

@ -0,0 +1,61 @@
<div class="uk-card">
<div class="uk-card-header space-y-2">
<h3 class="uk-h3">Create an account</h3>
<p class="text-muted-foreground">
Enter your email below to create your account
</p>
</div>
<div class="uk-card-body space-y-4">
<div class="grid grid-cols-2 gap-6">
<button class="uk-btn uk-btn-default">
<svg viewBox="0 0 438.549 438.549" class="mr-2 h-4 w-4">
<path
fill="currentColor"
d="M409.132 114.573c-19.608-33.596-46.205-60.194-79.798-79.8-33.598-19.607-70.277-29.408-110.063-29.408-39.781 0-76.472 9.804-110.063 29.408-33.596 19.605-60.192 46.204-79.8 79.8C9.803 148.168 0 184.854 0 224.63c0 47.78 13.94 90.745 41.827 128.906 27.884 38.164 63.906 64.572 108.063 79.227 5.14.954 8.945.283 11.419-1.996 2.475-2.282 3.711-5.14 3.711-8.562 0-.571-.049-5.708-.144-15.417a2549.81 2549.81 0 01-.144-25.406l-6.567 1.136c-4.187.767-9.469 1.092-15.846 1-6.374-.089-12.991-.757-19.842-1.999-6.854-1.231-13.229-4.086-19.13-8.559-5.898-4.473-10.085-10.328-12.56-17.556l-2.855-6.57c-1.903-4.374-4.899-9.233-8.992-14.559-4.093-5.331-8.232-8.945-12.419-10.848l-1.999-1.431c-1.332-.951-2.568-2.098-3.711-3.429-1.142-1.331-1.997-2.663-2.568-3.997-.572-1.335-.098-2.43 1.427-3.289 1.525-.859 4.281-1.276 8.28-1.276l5.708.853c3.807.763 8.516 3.042 14.133 6.851 5.614 3.806 10.229 8.754 13.846 14.842 4.38 7.806 9.657 13.754 15.846 17.847 6.184 4.093 12.419 6.136 18.699 6.136 6.28 0 11.704-.476 16.274-1.423 4.565-.952 8.848-2.383 12.847-4.285 1.713-12.758 6.377-22.559 13.988-29.41-10.848-1.14-20.601-2.857-29.264-5.14-8.658-2.286-17.605-5.996-26.835-11.14-9.235-5.137-16.896-11.516-22.985-19.126-6.09-7.614-11.088-17.61-14.987-29.979-3.901-12.374-5.852-26.648-5.852-42.826 0-23.035 7.52-42.637 22.557-58.817-7.044-17.318-6.379-36.732 1.997-58.24 5.52-1.715 13.706-.428 24.554 3.853 10.85 4.283 18.794 7.952 23.84 10.994 5.046 3.041 9.089 5.618 12.135 7.708 17.705-4.947 35.976-7.421 54.818-7.421s37.117 2.474 54.823 7.421l10.849-6.849c7.419-4.57 16.18-8.758 26.262-12.565 10.088-3.805 17.802-4.853 23.134-3.138 8.562 21.509 9.325 40.922 2.279 58.24 15.036 16.18 22.559 35.787 22.559 58.817 0 16.178-1.958 30.497-5.853 42.966-3.9 12.471-8.941 22.457-15.125 29.979-6.191 7.521-13.901 13.85-23.131 18.986-9.232 5.14-18.182 8.85-26.84 11.136-8.662 2.286-18.415 4.004-29.263 5.146 9.894 8.562 14.842 22.077 14.842 40.539v60.237c0 3.422 1.19 6.279 3.572 8.562 2.379 2.279 6.136 2.95 11.276 1.995 44.163-14.653 80.185-41.062 108.068-79.226 27.88-38.161 41.825-81.126 41.825-128.906-.01-39.771-9.818-76.454-29.414-110.049z"
></path>
</svg>
Github
</button>
<button class="uk-btn uk-btn-default">
<svg role="img" viewBox="0 0 24 24" class="mr-2 h-4 w-4">
<path
fill="currentColor"
d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z"
></path>
</svg>
Google
</button>
</div>
<div class="relative">
<div class="absolute inset-0 flex items-center">
<span class="w-full border-t border-border"></span>
</div>
<div class="relative flex justify-center text-xs uppercase">
<span class="bg-background px-2 text-muted-foreground"
>Or continue with</span
>
</div>
</div>
<div class="space-y-2">
<label class="uk-form-label" for="email">Email</label>
<input
class="uk-input"
id="email"
type="text"
placeholder="m@example.com"
/>
</div>
<div class="space-y-2">
<label class="uk-form-label" for="password">Password</label>
<input
class="uk-input"
id="password"
type="password"
placeholder="Password"
/>
</div>
</div>
<div class="uk-card-footer">
<button class="uk-btn uk-btn-primary w-full">Create account</button>
</div>
</div>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,142 @@
<body
class="bg-background font-geist-sans text-sm text-foreground"
data-sveltekit-preload-data="hover"
>
<div style="display: contents">
<!--[--><!--[--><!----><!---->
<div class="hidden h-screen grid-cols-2 xl:grid">
<div
class="col-span-1 hidden flex-col justify-between bg-zinc-900 p-8 text-white lg:flex"
>
<div class="flex items-center text-lg font-medium">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="mr-2 h-6 w-6"
>
<path
d="M15 6v12a3 3 0 1 0 3-3H6a3 3 0 1 0 3 3V6a3 3 0 1 0-3 3h12a3 3 0 1 0-3-3"
></path>
</svg>
Acme Inc
</div>
<blockquote class="space-y-2">
<p class="text-lg">
"This library has saved me countless hours of work and helped me
deliver stunning designs to my clients faster than ever before."
</p>
<footer class="text-sm">Sofia Davis</footer>
</blockquote>
</div>
<div class="col-span-2 flex flex-col p-8 lg:col-span-1">
<div class="flex flex-none justify-end">
<button class="uk-btn uk-btn-ghost">Login</button>
</div>
<div class="flex flex-1 items-center justify-center">
<div class="w-80 space-y-6">
<div class="flex flex-col space-y-2 text-center">
<h1 class="uk-h3">Create an account</h1>
<p class="text-sm text-muted-foreground">
Enter your email below to create your account
</p>
</div>
<div class="space-y-2">
<input
class="uk-input"
placeholder="name@example.com"
type="text"
/>
<button class="uk-btn uk-btn-primary w-full">
<!--[!--><!--]-->
Sign in with Email
</button>
</div>
<div class="relative">
<div class="absolute inset-0 flex items-center">
<span class="w-full border-t border-border"></span>
</div>
<div class="relative flex justify-center text-xs uppercase">
<span class="bg-background px-2 text-muted-foreground"
>Or continue with</span
>
</div>
</div>
<button class="uk-btn uk-btn-default w-full">
<svg viewBox="0 0 438.549 438.549" class="mr-2 h-4 w-4">
<path
fill="currentColor"
d="M409.132 114.573c-19.608-33.596-46.205-60.194-79.798-79.8-33.598-19.607-70.277-29.408-110.063-29.408-39.781 0-76.472 9.804-110.063 29.408-33.596 19.605-60.192 46.204-79.8 79.8C9.803 148.168 0 184.854 0 224.63c0 47.78 13.94 90.745 41.827 128.906 27.884 38.164 63.906 64.572 108.063 79.227 5.14.954 8.945.283 11.419-1.996 2.475-2.282 3.711-5.14 3.711-8.562 0-.571-.049-5.708-.144-15.417a2549.81 2549.81 0 01-.144-25.406l-6.567 1.136c-4.187.767-9.469 1.092-15.846 1-6.374-.089-12.991-.757-19.842-1.999-6.854-1.231-13.229-4.086-19.13-8.559-5.898-4.473-10.085-10.328-12.56-17.556l-2.855-6.57c-1.903-4.374-4.899-9.233-8.992-14.559-4.093-5.331-8.232-8.945-12.419-10.848l-1.999-1.431c-1.332-.951-2.568-2.098-3.711-3.429-1.142-1.331-1.997-2.663-2.568-3.997-.572-1.335-.098-2.43 1.427-3.289 1.525-.859 4.281-1.276 8.28-1.276l5.708.853c3.807.763 8.516 3.042 14.133 6.851 5.614 3.806 10.229 8.754 13.846 14.842 4.38 7.806 9.657 13.754 15.846 17.847 6.184 4.093 12.419 6.136 18.699 6.136 6.28 0 11.704-.476 16.274-1.423 4.565-.952 8.848-2.383 12.847-4.285 1.713-12.758 6.377-22.559 13.988-29.41-10.848-1.14-20.601-2.857-29.264-5.14-8.658-2.286-17.605-5.996-26.835-11.14-9.235-5.137-16.896-11.516-22.985-19.126-6.09-7.614-11.088-17.61-14.987-29.979-3.901-12.374-5.852-26.648-5.852-42.826 0-23.035 7.52-42.637 22.557-58.817-7.044-17.318-6.379-36.732 1.997-58.24 5.52-1.715 13.706-.428 24.554 3.853 10.85 4.283 18.794 7.952 23.84 10.994 5.046 3.041 9.089 5.618 12.135 7.708 17.705-4.947 35.976-7.421 54.818-7.421s37.117 2.474 54.823 7.421l10.849-6.849c7.419-4.57 16.18-8.758 26.262-12.565 10.088-3.805 17.802-4.853 23.134-3.138 8.562 21.509 9.325 40.922 2.279 58.24 15.036 16.18 22.559 35.787 22.559 58.817 0 16.178-1.958 30.497-5.853 42.966-3.9 12.471-8.941 22.457-15.125 29.979-6.191 7.521-13.901 13.85-23.131 18.986-9.232 5.14-18.182 8.85-26.84 11.136-8.662 2.286-18.415 4.004-29.263 5.146 9.894 8.562 14.842 22.077 14.842 40.539v60.237c0 3.422 1.19 6.279 3.572 8.562 2.379 2.279 6.136 2.95 11.276 1.995 44.163-14.653 80.185-41.062 108.068-79.226 27.88-38.161 41.825-81.126 41.825-128.906-.01-39.771-9.818-76.454-29.414-110.049z"
></path>
</svg>
Github
</button>
<p class="px-8 text-center text-sm text-muted-foreground">
By clicking continue, you agree to our
<a
class="underline underline-offset-4 hover:text-primary"
href="#"
>Terms of Service</a
>
and
<a
class="underline underline-offset-4 hover:text-primary"
href="#"
>Privacy Policy</a
>.
</p>
</div>
</div>
</div>
</div>
<!----><!----><!----><!--]-->
<!--[!-->
<div
id="svelte-announcer"
aria-live="assertive"
aria-atomic="true"
style="
position: absolute;
left: 0;
top: 0;
clip: rect(0 0 0 0);
clip-path: inset(50%);
overflow: hidden;
white-space: nowrap;
width: 1px;
height: 1px;
"
>
<!---->
</div>
<!--]--><!--]-->
<script>
{
__sveltekit_ceme51 = {
base: new URL("..", location).pathname.slice(0, -1),
};
const element = document.currentScript.parentElement;
const data = [null, null];
Promise.all([
import("../_app/immutable/entry/start.Vst7ySbz.js"),
import("../_app/immutable/entry/app.D3_5gIyu.js"),
]).then(([kit, app]) => {
kit.start(app, element, {
node_ids: [0, 3],
data,
form: null,
error: null,
});
});
}
</script>
</div>
</body>

185
Web/public/auth.html Normal file
View file

@ -0,0 +1,185 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Echoes Behind Closed Doors</title>
<!-- favicons -->
<link
rel="apple-touch-icon"
sizes="180x180"
href="/png/apple-touch-icon.png"
/>
<link rel="icon" type="image/x-icon" href="/ico/favicon.ico" />
<link
rel="icon"
type="image/png"
sizes="32x32"
href="/png/favicon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="/png/favicon-16x16.png"
/>
<link rel="manifest" href="/site.webmanifest" />
<!-- TODO: social share -->
<!-- ui stuff -->
<!-- temporary ui bundling fix (https://github.com/oven-sh/bun/issues/17243) -->
<script type="module" src="/js/ebcd-common-franken-ui.js"></script>
<link
rel="stylesheet"
href="https://unpkg.com/franken-ui@2.0.0-internal.42/dist/css/core.min.css"
/>
<script src="https://unpkg.com/@tailwindcss/browser@4"></script>
<style>
/* latin-ext */
@font-face {
font-family: "Geist";
font-style: normal;
font-weight: 100 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/geist/v1/gyByhwUxId8gMEwSGFWNPoTcZY7pVQ.woff2)
format("woff2");
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
U+A720-A7FF;
}
/* latin */
@font-face {
font-family: "Geist";
font-style: normal;
font-weight: 100 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/geist/v1/gyByhwUxId8gMEwcGFWNPoTcZY4.woff2)
format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
font-family: "Geist Mono";
font-style: normal;
font-weight: 100 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/geistmono/v1/or3nQ6H-1_WfwkMZI_qYFrkdmhHijks9bNn0.woff2)
format("woff2");
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
U+A720-A7FF;
}
/* latin */
@font-face {
font-family: "Geist Mono";
font-style: normal;
font-weight: 100 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/geistmono/v1/or3nQ6H-1_WfwkMZI_qYFrcdmhHijks9bA.woff2)
format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@theme {
--font-sans: "Geist", sans-serif;
--font-mono: "'Geist Mono'", monospace;
}
:root {
font-family: Geist, sans-serif;
font-feature-settings: "liga" 1, "calt" 1; /* fix for Chrome */
}
@media (max-width: 768px) {
.uk-subnav > * > :first-child {
padding-left: 0.5rem !important;
padding-right: 0.5rem !important;
}
}
</style>
</head>
<body class="bg-background text-foreground">
<main class="flex flex-col items-center justify-center h-screen">
<div class="w-80 !space-y-6">
<div class="flex flex-col !space-y-2 text-center">
<h1 class="uk-h3">Authenticate with Us</h1>
<p class="text-sm text-muted-foreground">
Log in with a magic link. No account yet? We'll make one!
</p>
</div>
<div class="!space-y-2">
<input
class="uk-input"
placeholder="name@example.com"
type="text"
/>
<button class="uk-btn uk-btn-primary w-full" href="#check-your-email" data-uk-toggle>
Send a Magic Link
</button>
</div>
<div class="relative">
<div class="absolute inset-0 flex items-center">
<span class="w-full border-t border-border"></span>
</div>
<div class="relative flex justify-center text-xs uppercase">
<span class="bg-background px-2 text-muted-foreground"
>Or continue with</span
>
</div>
</div>
<button class="uk-btn uk-btn-default w-full">
<svg role="img" viewBox="0 0 24 24" class="mr-2 h-4 w-4">
<path
fill="currentColor"
d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z"
></path>
</svg>
Google
</button>
<!-- <p class="px-8 text-center text-sm text-muted-foreground">
By clicking continue, you agree to our
<a
class="underline underline-offset-4 hover:text-primary"
href="#"
>Terms of Service</a
>
and
<a
class="underline underline-offset-4 hover:text-primary"
href="#"
>Privacy Policy</a
>.
</p> -->
</div>
</main>
<div id="check-your-email" class="uk-flex-top" data-uk-modal>
<div class="uk-modal-dialog uk-margin-auto-vertical">
<button
class="uk-modal-close absolute right-4 top-4"
type="button"
data-uk-close
></button>
<div class="uk-modal-header">
<h2 class="uk-modal-title">You've Got Mail!</h2>
</div>
<div class="uk-modal-body">
<p>
We've sent you an email with a magical link to authenticate with us.
If you're a new user, you'll make an account. If you're an existing
user, you'll be logged in. Check your inbox!
</p>
</div>
<div class="uk-modal-footer uk-text-right">
<button class="uk-modal-close uk-btn uk-btn-default">Okay!</button>
</div>
</div>
</div>
<script type="module" src="/js/ebcd-auth.js"></script>
</body>
</html>

View file

@ -0,0 +1,68 @@
/* @import url("https://unpkg.com/franken-ui@2.0.0-internal.42/dist/css/core.min.css"); */
@import "./franken-core.css";
@import "tailwindcss";
/* latin-ext */
@font-face {
font-family: "Geist";
font-style: normal;
font-weight: 100 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/geist/v1/gyByhwUxId8gMEwSGFWNPoTcZY7pVQ.woff2)
format("woff2");
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: "Geist";
font-style: normal;
font-weight: 100 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/geist/v1/gyByhwUxId8gMEwcGFWNPoTcZY4.woff2)
format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
font-family: "Geist Mono";
font-style: normal;
font-weight: 100 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/geistmono/v1/or3nQ6H-1_WfwkMZI_qYFrkdmhHijks9bNn0.woff2)
format("woff2");
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: "Geist Mono";
font-style: normal;
font-weight: 100 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/geistmono/v1/or3nQ6H-1_WfwkMZI_qYFrcdmhHijks9bA.woff2)
format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
U+2212, U+2215, U+FEFF, U+FFFD;
}
@theme {
--font-sans: "Geist", sans-serif;
--font-mono: "'Geist Mono'", monospace;
}
:root {
font-family: Geist, sans-serif;
font-feature-settings: "liga" 1, "calt" 1; /* fix for Chrome */
}
@media (max-width: 768px) {
.uk-subnav > * > :first-child {
padding-left: 0.5rem !important;
padding-right: 0.5rem !important;
}
}

View file

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -1,606 +0,0 @@
// js/nayuki-qrcodegen-v1.8.0.js
var qrcodegen;
(function(qrcodegen2) {
class QrCode {
constructor(version, errorCorrectionLevel, dataCodewords, msk) {
this.version = version;
this.errorCorrectionLevel = errorCorrectionLevel;
this.modules = [];
this.isFunction = [];
if (version < QrCode.MIN_VERSION || version > QrCode.MAX_VERSION)
throw new RangeError("Version value out of range");
if (msk < -1 || msk > 7)
throw new RangeError("Mask value out of range");
this.size = version * 4 + 17;
let row = [];
for (let i = 0;i < this.size; i++)
row.push(false);
for (let i = 0;i < this.size; i++) {
this.modules.push(row.slice());
this.isFunction.push(row.slice());
}
this.drawFunctionPatterns();
const allCodewords = this.addEccAndInterleave(dataCodewords);
this.drawCodewords(allCodewords);
if (msk == -1) {
let minPenalty = 1e9;
for (let i = 0;i < 8; i++) {
this.applyMask(i);
this.drawFormatBits(i);
const penalty = this.getPenaltyScore();
if (penalty < minPenalty) {
msk = i;
minPenalty = penalty;
}
this.applyMask(i);
}
}
assert(0 <= msk && msk <= 7);
this.mask = msk;
this.applyMask(msk);
this.drawFormatBits(msk);
this.isFunction = [];
}
static encodeText(text, ecl) {
const segs = qrcodegen2.QrSegment.makeSegments(text);
return QrCode.encodeSegments(segs, ecl);
}
static encodeBinary(data, ecl) {
const seg = qrcodegen2.QrSegment.makeBytes(data);
return QrCode.encodeSegments([seg], ecl);
}
static encodeSegments(segs, ecl, minVersion = 1, maxVersion = 40, mask = -1, boostEcl = true) {
if (!(QrCode.MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= QrCode.MAX_VERSION) || mask < -1 || mask > 7)
throw new RangeError("Invalid value");
let version;
let dataUsedBits;
for (version = minVersion;; version++) {
const dataCapacityBits2 = QrCode.getNumDataCodewords(version, ecl) * 8;
const usedBits = QrSegment.getTotalBits(segs, version);
if (usedBits <= dataCapacityBits2) {
dataUsedBits = usedBits;
break;
}
if (version >= maxVersion)
throw new RangeError("Data too long");
}
for (const newEcl of [QrCode.Ecc.MEDIUM, QrCode.Ecc.QUARTILE, QrCode.Ecc.HIGH]) {
if (boostEcl && dataUsedBits <= QrCode.getNumDataCodewords(version, newEcl) * 8)
ecl = newEcl;
}
let bb = [];
for (const seg of segs) {
appendBits(seg.mode.modeBits, 4, bb);
appendBits(seg.numChars, seg.mode.numCharCountBits(version), bb);
for (const b of seg.getData())
bb.push(b);
}
assert(bb.length == dataUsedBits);
const dataCapacityBits = QrCode.getNumDataCodewords(version, ecl) * 8;
assert(bb.length <= dataCapacityBits);
appendBits(0, Math.min(4, dataCapacityBits - bb.length), bb);
appendBits(0, (8 - bb.length % 8) % 8, bb);
assert(bb.length % 8 == 0);
for (let padByte = 236;bb.length < dataCapacityBits; padByte ^= 236 ^ 17)
appendBits(padByte, 8, bb);
let dataCodewords = [];
while (dataCodewords.length * 8 < bb.length)
dataCodewords.push(0);
bb.forEach((b, i) => dataCodewords[i >>> 3] |= b << 7 - (i & 7));
return new QrCode(version, ecl, dataCodewords, mask);
}
getModule(x, y) {
return 0 <= x && x < this.size && 0 <= y && y < this.size && this.modules[y][x];
}
drawFunctionPatterns() {
for (let i = 0;i < this.size; i++) {
this.setFunctionModule(6, i, i % 2 == 0);
this.setFunctionModule(i, 6, i % 2 == 0);
}
this.drawFinderPattern(3, 3);
this.drawFinderPattern(this.size - 4, 3);
this.drawFinderPattern(3, this.size - 4);
const alignPatPos = this.getAlignmentPatternPositions();
const numAlign = alignPatPos.length;
for (let i = 0;i < numAlign; i++) {
for (let j = 0;j < numAlign; j++) {
if (!(i == 0 && j == 0 || i == 0 && j == numAlign - 1 || i == numAlign - 1 && j == 0))
this.drawAlignmentPattern(alignPatPos[i], alignPatPos[j]);
}
}
this.drawFormatBits(0);
this.drawVersion();
}
drawFormatBits(mask) {
const data = this.errorCorrectionLevel.formatBits << 3 | mask;
let rem = data;
for (let i = 0;i < 10; i++)
rem = rem << 1 ^ (rem >>> 9) * 1335;
const bits = (data << 10 | rem) ^ 21522;
assert(bits >>> 15 == 0);
for (let i = 0;i <= 5; i++)
this.setFunctionModule(8, i, getBit(bits, i));
this.setFunctionModule(8, 7, getBit(bits, 6));
this.setFunctionModule(8, 8, getBit(bits, 7));
this.setFunctionModule(7, 8, getBit(bits, 8));
for (let i = 9;i < 15; i++)
this.setFunctionModule(14 - i, 8, getBit(bits, i));
for (let i = 0;i < 8; i++)
this.setFunctionModule(this.size - 1 - i, 8, getBit(bits, i));
for (let i = 8;i < 15; i++)
this.setFunctionModule(8, this.size - 15 + i, getBit(bits, i));
this.setFunctionModule(8, this.size - 8, true);
}
drawVersion() {
if (this.version < 7)
return;
let rem = this.version;
for (let i = 0;i < 12; i++)
rem = rem << 1 ^ (rem >>> 11) * 7973;
const bits = this.version << 12 | rem;
assert(bits >>> 18 == 0);
for (let i = 0;i < 18; i++) {
const color = getBit(bits, i);
const a = this.size - 11 + i % 3;
const b = Math.floor(i / 3);
this.setFunctionModule(a, b, color);
this.setFunctionModule(b, a, color);
}
}
drawFinderPattern(x, y) {
for (let dy = -4;dy <= 4; dy++) {
for (let dx = -4;dx <= 4; dx++) {
const dist = Math.max(Math.abs(dx), Math.abs(dy));
const xx = x + dx;
const yy = y + dy;
if (0 <= xx && xx < this.size && 0 <= yy && yy < this.size)
this.setFunctionModule(xx, yy, dist != 2 && dist != 4);
}
}
}
drawAlignmentPattern(x, y) {
for (let dy = -2;dy <= 2; dy++) {
for (let dx = -2;dx <= 2; dx++)
this.setFunctionModule(x + dx, y + dy, Math.max(Math.abs(dx), Math.abs(dy)) != 1);
}
}
setFunctionModule(x, y, isDark) {
this.modules[y][x] = isDark;
this.isFunction[y][x] = true;
}
addEccAndInterleave(data) {
const ver = this.version;
const ecl = this.errorCorrectionLevel;
if (data.length != QrCode.getNumDataCodewords(ver, ecl))
throw new RangeError("Invalid argument");
const numBlocks = QrCode.NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal][ver];
const blockEccLen = QrCode.ECC_CODEWORDS_PER_BLOCK[ecl.ordinal][ver];
const rawCodewords = Math.floor(QrCode.getNumRawDataModules(ver) / 8);
const numShortBlocks = numBlocks - rawCodewords % numBlocks;
const shortBlockLen = Math.floor(rawCodewords / numBlocks);
let blocks = [];
const rsDiv = QrCode.reedSolomonComputeDivisor(blockEccLen);
for (let i = 0, k = 0;i < numBlocks; i++) {
let dat = data.slice(k, k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1));
k += dat.length;
const ecc = QrCode.reedSolomonComputeRemainder(dat, rsDiv);
if (i < numShortBlocks)
dat.push(0);
blocks.push(dat.concat(ecc));
}
let result = [];
for (let i = 0;i < blocks[0].length; i++) {
blocks.forEach((block, j) => {
if (i != shortBlockLen - blockEccLen || j >= numShortBlocks)
result.push(block[i]);
});
}
assert(result.length == rawCodewords);
return result;
}
drawCodewords(data) {
if (data.length != Math.floor(QrCode.getNumRawDataModules(this.version) / 8))
throw new RangeError("Invalid argument");
let i = 0;
for (let right = this.size - 1;right >= 1; right -= 2) {
if (right == 6)
right = 5;
for (let vert = 0;vert < this.size; vert++) {
for (let j = 0;j < 2; j++) {
const x = right - j;
const upward = (right + 1 & 2) == 0;
const y = upward ? this.size - 1 - vert : vert;
if (!this.isFunction[y][x] && i < data.length * 8) {
this.modules[y][x] = getBit(data[i >>> 3], 7 - (i & 7));
i++;
}
}
}
}
assert(i == data.length * 8);
}
applyMask(mask) {
if (mask < 0 || mask > 7)
throw new RangeError("Mask value out of range");
for (let y = 0;y < this.size; y++) {
for (let x = 0;x < this.size; x++) {
let invert;
switch (mask) {
case 0:
invert = (x + y) % 2 == 0;
break;
case 1:
invert = y % 2 == 0;
break;
case 2:
invert = x % 3 == 0;
break;
case 3:
invert = (x + y) % 3 == 0;
break;
case 4:
invert = (Math.floor(x / 3) + Math.floor(y / 2)) % 2 == 0;
break;
case 5:
invert = x * y % 2 + x * y % 3 == 0;
break;
case 6:
invert = (x * y % 2 + x * y % 3) % 2 == 0;
break;
case 7:
invert = ((x + y) % 2 + x * y % 3) % 2 == 0;
break;
default:
throw new Error("Unreachable");
}
if (!this.isFunction[y][x] && invert)
this.modules[y][x] = !this.modules[y][x];
}
}
}
getPenaltyScore() {
let result = 0;
for (let y = 0;y < this.size; y++) {
let runColor = false;
let runX = 0;
let runHistory = [0, 0, 0, 0, 0, 0, 0];
for (let x = 0;x < this.size; x++) {
if (this.modules[y][x] == runColor) {
runX++;
if (runX == 5)
result += QrCode.PENALTY_N1;
else if (runX > 5)
result++;
} else {
this.finderPenaltyAddHistory(runX, runHistory);
if (!runColor)
result += this.finderPenaltyCountPatterns(runHistory) * QrCode.PENALTY_N3;
runColor = this.modules[y][x];
runX = 1;
}
}
result += this.finderPenaltyTerminateAndCount(runColor, runX, runHistory) * QrCode.PENALTY_N3;
}
for (let x = 0;x < this.size; x++) {
let runColor = false;
let runY = 0;
let runHistory = [0, 0, 0, 0, 0, 0, 0];
for (let y = 0;y < this.size; y++) {
if (this.modules[y][x] == runColor) {
runY++;
if (runY == 5)
result += QrCode.PENALTY_N1;
else if (runY > 5)
result++;
} else {
this.finderPenaltyAddHistory(runY, runHistory);
if (!runColor)
result += this.finderPenaltyCountPatterns(runHistory) * QrCode.PENALTY_N3;
runColor = this.modules[y][x];
runY = 1;
}
}
result += this.finderPenaltyTerminateAndCount(runColor, runY, runHistory) * QrCode.PENALTY_N3;
}
for (let y = 0;y < this.size - 1; y++) {
for (let x = 0;x < this.size - 1; x++) {
const color = this.modules[y][x];
if (color == this.modules[y][x + 1] && color == this.modules[y + 1][x] && color == this.modules[y + 1][x + 1])
result += QrCode.PENALTY_N2;
}
}
let dark = 0;
for (const row of this.modules)
dark = row.reduce((sum, color) => sum + (color ? 1 : 0), dark);
const total = this.size * this.size;
const k = Math.ceil(Math.abs(dark * 20 - total * 10) / total) - 1;
assert(0 <= k && k <= 9);
result += k * QrCode.PENALTY_N4;
assert(0 <= result && result <= 2568888);
return result;
}
getAlignmentPatternPositions() {
if (this.version == 1)
return [];
else {
const numAlign = Math.floor(this.version / 7) + 2;
const step = this.version == 32 ? 26 : Math.ceil((this.version * 4 + 4) / (numAlign * 2 - 2)) * 2;
let result = [6];
for (let pos = this.size - 7;result.length < numAlign; pos -= step)
result.splice(1, 0, pos);
return result;
}
}
static getNumRawDataModules(ver) {
if (ver < QrCode.MIN_VERSION || ver > QrCode.MAX_VERSION)
throw new RangeError("Version number out of range");
let result = (16 * ver + 128) * ver + 64;
if (ver >= 2) {
const numAlign = Math.floor(ver / 7) + 2;
result -= (25 * numAlign - 10) * numAlign - 55;
if (ver >= 7)
result -= 36;
}
assert(208 <= result && result <= 29648);
return result;
}
static getNumDataCodewords(ver, ecl) {
return Math.floor(QrCode.getNumRawDataModules(ver) / 8) - QrCode.ECC_CODEWORDS_PER_BLOCK[ecl.ordinal][ver] * QrCode.NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal][ver];
}
static reedSolomonComputeDivisor(degree) {
if (degree < 1 || degree > 255)
throw new RangeError("Degree out of range");
let result = [];
for (let i = 0;i < degree - 1; i++)
result.push(0);
result.push(1);
let root = 1;
for (let i = 0;i < degree; i++) {
for (let j = 0;j < result.length; j++) {
result[j] = QrCode.reedSolomonMultiply(result[j], root);
if (j + 1 < result.length)
result[j] ^= result[j + 1];
}
root = QrCode.reedSolomonMultiply(root, 2);
}
return result;
}
static reedSolomonComputeRemainder(data, divisor) {
let result = divisor.map((_) => 0);
for (const b of data) {
const factor = b ^ result.shift();
result.push(0);
divisor.forEach((coef, i) => result[i] ^= QrCode.reedSolomonMultiply(coef, factor));
}
return result;
}
static reedSolomonMultiply(x, y) {
if (x >>> 8 != 0 || y >>> 8 != 0)
throw new RangeError("Byte out of range");
let z = 0;
for (let i = 7;i >= 0; i--) {
z = z << 1 ^ (z >>> 7) * 285;
z ^= (y >>> i & 1) * x;
}
assert(z >>> 8 == 0);
return z;
}
finderPenaltyCountPatterns(runHistory) {
const n = runHistory[1];
assert(n <= this.size * 3);
const core = n > 0 && runHistory[2] == n && runHistory[3] == n * 3 && runHistory[4] == n && runHistory[5] == n;
return (core && runHistory[0] >= n * 4 && runHistory[6] >= n ? 1 : 0) + (core && runHistory[6] >= n * 4 && runHistory[0] >= n ? 1 : 0);
}
finderPenaltyTerminateAndCount(currentRunColor, currentRunLength, runHistory) {
if (currentRunColor) {
this.finderPenaltyAddHistory(currentRunLength, runHistory);
currentRunLength = 0;
}
currentRunLength += this.size;
this.finderPenaltyAddHistory(currentRunLength, runHistory);
return this.finderPenaltyCountPatterns(runHistory);
}
finderPenaltyAddHistory(currentRunLength, runHistory) {
if (runHistory[0] == 0)
currentRunLength += this.size;
runHistory.pop();
runHistory.unshift(currentRunLength);
}
}
QrCode.MIN_VERSION = 1;
QrCode.MAX_VERSION = 40;
QrCode.PENALTY_N1 = 3;
QrCode.PENALTY_N2 = 3;
QrCode.PENALTY_N3 = 40;
QrCode.PENALTY_N4 = 10;
QrCode.ECC_CODEWORDS_PER_BLOCK = [
[-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],
[-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28],
[-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],
[-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]
];
QrCode.NUM_ERROR_CORRECTION_BLOCKS = [
[-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25],
[-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49],
[-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68],
[-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81]
];
qrcodegen2.QrCode = QrCode;
function appendBits(val, len, bb) {
if (len < 0 || len > 31 || val >>> len != 0)
throw new RangeError("Value out of range");
for (let i = len - 1;i >= 0; i--)
bb.push(val >>> i & 1);
}
function getBit(x, i) {
return (x >>> i & 1) != 0;
}
function assert(cond) {
if (!cond)
throw new Error("Assertion error");
}
class QrSegment {
constructor(mode, numChars, bitData) {
this.mode = mode;
this.numChars = numChars;
this.bitData = bitData;
if (numChars < 0)
throw new RangeError("Invalid argument");
this.bitData = bitData.slice();
}
static makeBytes(data) {
let bb = [];
for (const b of data)
appendBits(b, 8, bb);
return new QrSegment(QrSegment.Mode.BYTE, data.length, bb);
}
static makeNumeric(digits) {
if (!QrSegment.isNumeric(digits))
throw new RangeError("String contains non-numeric characters");
let bb = [];
for (let i = 0;i < digits.length; ) {
const n = Math.min(digits.length - i, 3);
appendBits(parseInt(digits.substr(i, n), 10), n * 3 + 1, bb);
i += n;
}
return new QrSegment(QrSegment.Mode.NUMERIC, digits.length, bb);
}
static makeAlphanumeric(text) {
if (!QrSegment.isAlphanumeric(text))
throw new RangeError("String contains unencodable characters in alphanumeric mode");
let bb = [];
let i;
for (i = 0;i + 2 <= text.length; i += 2) {
let temp = QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45;
temp += QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1));
appendBits(temp, 11, bb);
}
if (i < text.length)
appendBits(QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6, bb);
return new QrSegment(QrSegment.Mode.ALPHANUMERIC, text.length, bb);
}
static makeSegments(text) {
if (text == "")
return [];
else if (QrSegment.isNumeric(text))
return [QrSegment.makeNumeric(text)];
else if (QrSegment.isAlphanumeric(text))
return [QrSegment.makeAlphanumeric(text)];
else
return [QrSegment.makeBytes(QrSegment.toUtf8ByteArray(text))];
}
static makeEci(assignVal) {
let bb = [];
if (assignVal < 0)
throw new RangeError("ECI assignment value out of range");
else if (assignVal < 1 << 7)
appendBits(assignVal, 8, bb);
else if (assignVal < 1 << 14) {
appendBits(2, 2, bb);
appendBits(assignVal, 14, bb);
} else if (assignVal < 1e6) {
appendBits(6, 3, bb);
appendBits(assignVal, 21, bb);
} else
throw new RangeError("ECI assignment value out of range");
return new QrSegment(QrSegment.Mode.ECI, 0, bb);
}
static isNumeric(text) {
return QrSegment.NUMERIC_REGEX.test(text);
}
static isAlphanumeric(text) {
return QrSegment.ALPHANUMERIC_REGEX.test(text);
}
getData() {
return this.bitData.slice();
}
static getTotalBits(segs, version) {
let result = 0;
for (const seg of segs) {
const ccbits = seg.mode.numCharCountBits(version);
if (seg.numChars >= 1 << ccbits)
return Infinity;
result += 4 + ccbits + seg.bitData.length;
}
return result;
}
static toUtf8ByteArray(str) {
str = encodeURI(str);
let result = [];
for (let i = 0;i < str.length; i++) {
if (str.charAt(i) != "%")
result.push(str.charCodeAt(i));
else {
result.push(parseInt(str.substr(i + 1, 2), 16));
i += 2;
}
}
return result;
}
}
QrSegment.NUMERIC_REGEX = /^[0-9]*$/;
QrSegment.ALPHANUMERIC_REGEX = /^[A-Z0-9 $%*+.\/:-]*$/;
QrSegment.ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
qrcodegen2.QrSegment = QrSegment;
})(qrcodegen || (qrcodegen = {}));
(function(qrcodegen2) {
var QrCode;
(function(QrCode2) {
class Ecc {
constructor(ordinal, formatBits) {
this.ordinal = ordinal;
this.formatBits = formatBits;
}
}
Ecc.LOW = new Ecc(0, 1);
Ecc.MEDIUM = new Ecc(1, 0);
Ecc.QUARTILE = new Ecc(2, 3);
Ecc.HIGH = new Ecc(3, 2);
QrCode2.Ecc = Ecc;
})(QrCode = qrcodegen2.QrCode || (qrcodegen2.QrCode = {}));
})(qrcodegen || (qrcodegen = {}));
(function(qrcodegen2) {
var QrSegment;
(function(QrSegment2) {
class Mode {
constructor(modeBits, numBitsCharCount) {
this.modeBits = modeBits;
this.numBitsCharCount = numBitsCharCount;
}
numCharCountBits(ver) {
return this.numBitsCharCount[Math.floor((ver + 7) / 17)];
}
}
Mode.NUMERIC = new Mode(1, [10, 12, 14]);
Mode.ALPHANUMERIC = new Mode(2, [9, 11, 13]);
Mode.BYTE = new Mode(4, [8, 16, 16]);
Mode.KANJI = new Mode(8, [8, 10, 12]);
Mode.ECI = new Mode(7, [0, 0, 0]);
QrSegment2.Mode = Mode;
})(QrSegment = qrcodegen2.QrSegment || (qrcodegen2.QrSegment = {}));
})(qrcodegen || (qrcodegen = {}));
// js/landing-qrcode.js
function toSvgString(qr, border, lightColor, darkColor) {
if (border < 0)
throw new RangeError("Border must be non-negative");
let parts = [];
for (let y = 0;y < qr.size; y++) {
for (let x = 0;x < qr.size; x++) {
if (qr.getModule(x, y))
parts.push(`M${x + border},${y + border}h1v1h-1z`);
}
}
return `<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 ${qr.size + border * 2} ${qr.size + border * 2}" stroke="none" style="width: 100%;" class="object-fit"><rect width="100%" height="100%" fill="${lightColor}"/><path d="${parts.join(" ")}" fill="${darkColor}"/></svg>
`;
}
function generateQrCode(text) {
return toSvgString(qrcodegen.QrCode.encodeText(text, qrcodegen.QrCode.Ecc.MEDIUM), 3, "#ffffff", "#000000");
}
var svg = generateQrCode(window.location.origin + "/signup.html");
document.getElementById("hero-svg").innerHTML = svg;
document.getElementById("hero-svg").classList.remove("uk-placeholder");

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -6,15 +6,31 @@
<title>Echoes Behind Closed Doors</title>
<!-- favicons -->
<link rel="apple-touch-icon" sizes="180x180" href="./apple-touch-icon-xhq3hzfq.png" />
<link rel="icon" type="image/x-icon" href="./favicon-4nk2rrtb.ico" />
<link rel="icon" type="image/png" sizes="32x32" href="./favicon-32x32-sqpfcyy0.png" />
<link rel="icon" type="image/png" sizes="16x16" href="./favicon-16x16-6gdgm8kp.png" />
<link rel="manifest" href="./site-h99v0pws.webmanifest" />
<link
rel="apple-touch-icon"
sizes="180x180"
href="/png/apple-touch-icon.png"
/>
<link rel="icon" type="image/x-icon" href="/ico/favicon.ico" />
<link
rel="icon"
type="image/png"
sizes="32x32"
href="/png/favicon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="/png/favicon-16x16.png"
/>
<link rel="manifest" href="/site.webmanifest" />
<!-- TODO: social share -->
<!-- TODO: temporary ui bundling fix (https://github.com/oven-sh/bun/issues/17243) -->
<!-- ui stuff -->
<!-- temporary ui bundling fix (https://github.com/oven-sh/bun/issues/17243) -->
<script type="module" src="/js/ebcd-common-franken-ui.js"></script>
<link
rel="stylesheet"
href="https://unpkg.com/franken-ui@2.0.0-internal.42/dist/css/core.min.css"
@ -71,7 +87,6 @@
U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@theme {
--font-sans: "Geist", sans-serif;
--font-mono: "'Geist Mono'", monospace;
@ -80,7 +95,6 @@
font-family: Geist, sans-serif;
font-feature-settings: "liga" 1, "calt" 1; /* fix for Chrome */
}
@media (max-width: 768px) {
.uk-subnav > * > :first-child {
padding-left: 0.5rem !important;
@ -88,12 +102,7 @@
}
}
</style>
<!-- franken-ui -->
<!-- TODO: temporary ui bundling fix (see above) -->
<!-- <link rel="stylesheet" href="/css/styles.css" /> -->
<script type="module" crossorigin src="./index-ra0608an.js"></script></head>
</head>
<body class="bg-background text-foreground">
<main>
<section
@ -120,8 +129,12 @@
data-uk-sticky="position:top"
>
<div class="flex flex-row gap-2">
<img src="./logo-icon-1yfzf2ex.png" alt="wirm logo" class="!h-[2.5rem]" />
<img src="./logo-wordmark-blue-x0tvrafq.png" alt="wirm wordmark" class="!h-[2.5rem]" />
<img src="/png/logo-icon.png" alt="wirm logo" class="!h-[2.5rem]" />
<img
src="/png/logo-wordmark-blue.png"
alt="wirm wordmark"
class="!h-[2.5rem]"
/>
</div>
<nav class="flex">
@ -135,21 +148,18 @@
<div data-uk-dropdown="mode: click">
<ul class="uk-dropdown-nav uk-nav">
<li id="nav-auth-logIn">
<a href="/login">Log In</a>
</li>
<li id="nav-auth-signUp">
<a href="/signup">Sign Up</a>
</li>
<li id="nav-auth-logOut">
<a href="/profile?logOut=true">Log Out</a>
<a href="/auth.html">Authenticate</a>
</li>
<li id="nav-auth-profile">
<a href="/profile">Profile</a>
<a href="/profile.html">Profile</a>
</li>
<li id="nav-auth-logOut">
<a href="/profile.html?logOut=true">Log Out</a>
</li>
</ul>
</div>
</li>
<li><a href="/booth">Manage Booth</a></li>
<li><a href="/booth.html">Manage Booth</a></li>
</ul>
</nav>
</header>
@ -274,6 +284,7 @@
</section>
</main>
<script type="module" src="/js/ebcd-landing-qrcode.js"></script>
<script type="module" src="/js/ebcd-common-navbar.js"></script>
</body>
</html>

View file

@ -0,0 +1,9 @@
import { auth } from "./ebcd-common-firebase.js";
console.log("ebcd-auth loaded <3");
auth.onAuthStateChanged((user) => {
if (user) {
window.location = "/profile.html";
}
});

View file

@ -0,0 +1,17 @@
import { initializeApp } from "https://www.gstatic.com/firebasejs/11.3.0/firebase-app.js";
import { getDatabase } from "https://www.gstatic.com/firebasejs/11.3.0/firebase-database.js";
import { getAuth } from "https://www.gstatic.com/firebasejs/11.3.0/firebase-auth.js";
const firebaseConfig = {
apiKey: "AIzaSyARm-eSymd2Q3AyxJXiAiiUzsXGmc6T72I",
authDomain: "echoesbehindcloseddoors.firebaseapp.com",
databaseURL: "https://echoesbehindcloseddoors-default-rtdb.asia-southeast1.firebasedatabase.app",
projectId: "echoesbehindcloseddoors",
storageBucket: "echoesbehindcloseddoors.firebasestorage.app",
messagingSenderId: "905742343227",
appId: "1:905742343227:web:19d04f77371ef1952c901e"
};
export const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
export const database = getDatabase(app);

View file

@ -0,0 +1,23 @@
import "https://unpkg.com/franken-ui@2.0.0-internal.42/dist/js/core.iife.js";
import "https://unpkg.com/franken-ui@2.0.0-internal.42/dist/js/icon.iife.js";
const htmlElement = document.documentElement;
const __FRANKEN__ = JSON.parse(
localStorage.getItem("__FRANKEN__") || "{}"
);
if (
__FRANKEN__.mode === "dark" ||
(!__FRANKEN__.mode &&
window.matchMedia("(prefers-color-scheme: dark)").matches)
) {
htmlElement.classList.add("dark");
} else {
htmlElement.classList.remove("dark");
}
htmlElement.classList.add(__FRANKEN__.theme || "uk-theme-blue");
htmlElement.classList.add(__FRANKEN__.radii || "uk-radii-md");
htmlElement.classList.add(__FRANKEN__.shadows || "uk-shadows-sm");
htmlElement.classList.add(__FRANKEN__.font || "uk-font-sm");

View file

@ -0,0 +1,20 @@
import { app, auth } from "./ebcd-common-firebase.js";
// the navbar has the following li elements in a dropdown:
// - nav-auth-logIn
// - nav-auth-signUp
// - nav-auth-profile
// - nav-auth-logOut
// are we logged in?
auth.onAuthStateChanged((user) => {
if (user) {
// signed in, only show the profile and log out links
document.getElementById("nav-auth-logIn").style.display = "none";
document.getElementById("nav-auth-signUp").style.display = "none";
} else {
// not signed in, only show the log in and sign up links
document.getElementById("nav-auth-profile").style.display = "none";
document.getElementById("nav-auth-logOut").style.display = "none";
}
});

View file

@ -0,0 +1,56 @@
/*
* modified from the typscript QR Code generator input demo
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* - The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* - The Software is provided "as is", without warranty of any kind, express or
* implied, including but not limited to the warranties of merchantability,
* fitness for a particular purpose and noninfringement. In no event shall the
* authors or copyright holders be liable for any claim, damages or other
* liability, whether in an action of contract, tort or otherwise, arising from,
* out of or in connection with the Software or the use or other dealings in the
* Software.
*/
import { qrcodegen } from "./nayuki-qrcodegen-v1.8.0.js";
function toSvgString(qr, border, lightColor, darkColor) {
if (border < 0) throw new RangeError("Border must be non-negative");
let parts = [];
for (let y = 0; y < qr.size; y++) {
for (let x = 0; x < qr.size; x++) {
if (qr.getModule(x, y))
parts.push(`M${x + border},${y + border}h1v1h-1z`);
}
}
return `<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 ${
qr.size + border * 2
} ${
qr.size + border * 2
}" stroke="none" style="width: 100%;" class="object-fit"><rect width="100%" height="100%" fill="${lightColor}"/><path d="${parts.join(
" "
)}" fill="${darkColor}"/></svg>
`;
}
function generateQrCode(text) {
return toSvgString(
qrcodegen.QrCode.encodeText(text, qrcodegen.QrCode.Ecc.MEDIUM),
3,
"#ffffff", // light
"#000000" // dark
);
}
const svg = generateQrCode(window.location.origin + "/signup.html");
document.getElementById("hero-svg").innerHTML = svg;
document.getElementById("hero-svg").classList.remove("uk-placeholder");

View file

@ -0,0 +1,837 @@
/*
* QR Code generator library (compiled from TypeScript)
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* - The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* - The Software is provided "as is", without warranty of any kind, express or
* implied, including but not limited to the warranties of merchantability,
* fitness for a particular purpose and noninfringement. In no event shall the
* authors or copyright holders be liable for any claim, damages or other
* liability, whether in an action of contract, tort or otherwise, arising from,
* out of or in connection with the Software or the use or other dealings in the
* Software.
*/
"use strict";
export var qrcodegen;
(function (qrcodegen) {
/*---- QR Code symbol class ----*/
/*
* A QR Code symbol, which is a type of two-dimension barcode.
* Invented by Denso Wave and described in the ISO/IEC 18004 standard.
* Instances of this class represent an immutable square grid of dark and light cells.
* The class provides static factory functions to create a QR Code from text or binary data.
* The class covers the QR Code Model 2 specification, supporting all versions (sizes)
* from 1 to 40, all 4 error correction levels, and 4 character encoding modes.
*
* Ways to create a QR Code object:
* - High level: Take the payload data and call QrCode.encodeText() or QrCode.encodeBinary().
* - Mid level: Custom-make the list of segments and call QrCode.encodeSegments().
* - Low level: Custom-make the array of data codeword bytes (including
* segment headers and final padding, excluding error correction codewords),
* supply the appropriate version number, and call the QrCode() constructor.
* (Note that all ways require supplying the desired error correction level.)
*/
class QrCode {
/*-- Constructor (low level) and fields --*/
// Creates a new QR Code with the given version number,
// error correction level, data codeword bytes, and mask number.
// This is a low-level API that most users should not use directly.
// A mid-level API is the encodeSegments() function.
constructor(
// The version number of this QR Code, which is between 1 and 40 (inclusive).
// This determines the size of this barcode.
version,
// The error correction level used in this QR Code.
errorCorrectionLevel, dataCodewords, msk) {
this.version = version;
this.errorCorrectionLevel = errorCorrectionLevel;
// The modules of this QR Code (false = light, true = dark).
// Immutable after constructor finishes. Accessed through getModule().
this.modules = [];
// Indicates function modules that are not subjected to masking. Discarded when constructor finishes.
this.isFunction = [];
// Check scalar arguments
if (version < QrCode.MIN_VERSION || version > QrCode.MAX_VERSION)
throw new RangeError("Version value out of range");
if (msk < -1 || msk > 7)
throw new RangeError("Mask value out of range");
this.size = version * 4 + 17;
// Initialize both grids to be size*size arrays of Boolean false
let row = [];
for (let i = 0; i < this.size; i++)
row.push(false);
for (let i = 0; i < this.size; i++) {
this.modules.push(row.slice()); // Initially all light
this.isFunction.push(row.slice());
}
// Compute ECC, draw modules
this.drawFunctionPatterns();
const allCodewords = this.addEccAndInterleave(dataCodewords);
this.drawCodewords(allCodewords);
// Do masking
if (msk == -1) { // Automatically choose best mask
let minPenalty = 1000000000;
for (let i = 0; i < 8; i++) {
this.applyMask(i);
this.drawFormatBits(i);
const penalty = this.getPenaltyScore();
if (penalty < minPenalty) {
msk = i;
minPenalty = penalty;
}
this.applyMask(i); // Undoes the mask due to XOR
}
}
assert(0 <= msk && msk <= 7);
this.mask = msk;
this.applyMask(msk); // Apply the final choice of mask
this.drawFormatBits(msk); // Overwrite old format bits
this.isFunction = [];
}
/*-- Static factory functions (high level) --*/
// Returns a QR Code representing the given Unicode text string at the given error correction level.
// As a conservative upper bound, this function is guaranteed to succeed for strings that have 738 or fewer
// Unicode code points (not UTF-16 code units) if the low error correction level is used. The smallest possible
// QR Code version is automatically chosen for the output. The ECC level of the result may be higher than the
// ecl argument if it can be done without increasing the version.
static encodeText(text, ecl) {
const segs = qrcodegen.QrSegment.makeSegments(text);
return QrCode.encodeSegments(segs, ecl);
}
// Returns a QR Code representing the given binary data at the given error correction level.
// This function always encodes using the binary segment mode, not any text mode. The maximum number of
// bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output.
// The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version.
static encodeBinary(data, ecl) {
const seg = qrcodegen.QrSegment.makeBytes(data);
return QrCode.encodeSegments([seg], ecl);
}
/*-- Static factory functions (mid level) --*/
// Returns a QR Code representing the given segments with the given encoding parameters.
// The smallest possible QR Code version within the given range is automatically
// chosen for the output. Iff boostEcl is true, then the ECC level of the result
// may be higher than the ecl argument if it can be done without increasing the
// version. The mask number is either between 0 to 7 (inclusive) to force that
// mask, or -1 to automatically choose an appropriate mask (which may be slow).
// This function allows the user to create a custom sequence of segments that switches
// between modes (such as alphanumeric and byte) to encode text in less space.
// This is a mid-level API; the high-level API is encodeText() and encodeBinary().
static encodeSegments(segs, ecl, minVersion = 1, maxVersion = 40, mask = -1, boostEcl = true) {
if (!(QrCode.MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= QrCode.MAX_VERSION)
|| mask < -1 || mask > 7)
throw new RangeError("Invalid value");
// Find the minimal version number to use
let version;
let dataUsedBits;
for (version = minVersion;; version++) {
const dataCapacityBits = QrCode.getNumDataCodewords(version, ecl) * 8; // Number of data bits available
const usedBits = QrSegment.getTotalBits(segs, version);
if (usedBits <= dataCapacityBits) {
dataUsedBits = usedBits;
break; // This version number is found to be suitable
}
if (version >= maxVersion) // All versions in the range could not fit the given data
throw new RangeError("Data too long");
}
// Increase the error correction level while the data still fits in the current version number
for (const newEcl of [QrCode.Ecc.MEDIUM, QrCode.Ecc.QUARTILE, QrCode.Ecc.HIGH]) { // From low to high
if (boostEcl && dataUsedBits <= QrCode.getNumDataCodewords(version, newEcl) * 8)
ecl = newEcl;
}
// Concatenate all segments to create the data bit string
let bb = [];
for (const seg of segs) {
appendBits(seg.mode.modeBits, 4, bb);
appendBits(seg.numChars, seg.mode.numCharCountBits(version), bb);
for (const b of seg.getData())
bb.push(b);
}
assert(bb.length == dataUsedBits);
// Add terminator and pad up to a byte if applicable
const dataCapacityBits = QrCode.getNumDataCodewords(version, ecl) * 8;
assert(bb.length <= dataCapacityBits);
appendBits(0, Math.min(4, dataCapacityBits - bb.length), bb);
appendBits(0, (8 - bb.length % 8) % 8, bb);
assert(bb.length % 8 == 0);
// Pad with alternating bytes until data capacity is reached
for (let padByte = 0xEC; bb.length < dataCapacityBits; padByte ^= 0xEC ^ 0x11)
appendBits(padByte, 8, bb);
// Pack bits into bytes in big endian
let dataCodewords = [];
while (dataCodewords.length * 8 < bb.length)
dataCodewords.push(0);
bb.forEach((b, i) => dataCodewords[i >>> 3] |= b << (7 - (i & 7)));
// Create the QR Code object
return new QrCode(version, ecl, dataCodewords, mask);
}
/*-- Accessor methods --*/
// Returns the color of the module (pixel) at the given coordinates, which is false
// for light or true for dark. The top left corner has the coordinates (x=0, y=0).
// If the given coordinates are out of bounds, then false (light) is returned.
getModule(x, y) {
return 0 <= x && x < this.size && 0 <= y && y < this.size && this.modules[y][x];
}
/*-- Private helper methods for constructor: Drawing function modules --*/
// Reads this object's version field, and draws and marks all function modules.
drawFunctionPatterns() {
// Draw horizontal and vertical timing patterns
for (let i = 0; i < this.size; i++) {
this.setFunctionModule(6, i, i % 2 == 0);
this.setFunctionModule(i, 6, i % 2 == 0);
}
// Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules)
this.drawFinderPattern(3, 3);
this.drawFinderPattern(this.size - 4, 3);
this.drawFinderPattern(3, this.size - 4);
// Draw numerous alignment patterns
const alignPatPos = this.getAlignmentPatternPositions();
const numAlign = alignPatPos.length;
for (let i = 0; i < numAlign; i++) {
for (let j = 0; j < numAlign; j++) {
// Don't draw on the three finder corners
if (!(i == 0 && j == 0 || i == 0 && j == numAlign - 1 || i == numAlign - 1 && j == 0))
this.drawAlignmentPattern(alignPatPos[i], alignPatPos[j]);
}
}
// Draw configuration data
this.drawFormatBits(0); // Dummy mask value; overwritten later in the constructor
this.drawVersion();
}
// Draws two copies of the format bits (with its own error correction code)
// based on the given mask and this object's error correction level field.
drawFormatBits(mask) {
// Calculate error correction code and pack bits
const data = this.errorCorrectionLevel.formatBits << 3 | mask; // errCorrLvl is uint2, mask is uint3
let rem = data;
for (let i = 0; i < 10; i++)
rem = (rem << 1) ^ ((rem >>> 9) * 0x537);
const bits = (data << 10 | rem) ^ 0x5412; // uint15
assert(bits >>> 15 == 0);
// Draw first copy
for (let i = 0; i <= 5; i++)
this.setFunctionModule(8, i, getBit(bits, i));
this.setFunctionModule(8, 7, getBit(bits, 6));
this.setFunctionModule(8, 8, getBit(bits, 7));
this.setFunctionModule(7, 8, getBit(bits, 8));
for (let i = 9; i < 15; i++)
this.setFunctionModule(14 - i, 8, getBit(bits, i));
// Draw second copy
for (let i = 0; i < 8; i++)
this.setFunctionModule(this.size - 1 - i, 8, getBit(bits, i));
for (let i = 8; i < 15; i++)
this.setFunctionModule(8, this.size - 15 + i, getBit(bits, i));
this.setFunctionModule(8, this.size - 8, true); // Always dark
}
// Draws two copies of the version bits (with its own error correction code),
// based on this object's version field, iff 7 <= version <= 40.
drawVersion() {
if (this.version < 7)
return;
// Calculate error correction code and pack bits
let rem = this.version; // version is uint6, in the range [7, 40]
for (let i = 0; i < 12; i++)
rem = (rem << 1) ^ ((rem >>> 11) * 0x1F25);
const bits = this.version << 12 | rem; // uint18
assert(bits >>> 18 == 0);
// Draw two copies
for (let i = 0; i < 18; i++) {
const color = getBit(bits, i);
const a = this.size - 11 + i % 3;
const b = Math.floor(i / 3);
this.setFunctionModule(a, b, color);
this.setFunctionModule(b, a, color);
}
}
// Draws a 9*9 finder pattern including the border separator,
// with the center module at (x, y). Modules can be out of bounds.
drawFinderPattern(x, y) {
for (let dy = -4; dy <= 4; dy++) {
for (let dx = -4; dx <= 4; dx++) {
const dist = Math.max(Math.abs(dx), Math.abs(dy)); // Chebyshev/infinity norm
const xx = x + dx;
const yy = y + dy;
if (0 <= xx && xx < this.size && 0 <= yy && yy < this.size)
this.setFunctionModule(xx, yy, dist != 2 && dist != 4);
}
}
}
// Draws a 5*5 alignment pattern, with the center module
// at (x, y). All modules must be in bounds.
drawAlignmentPattern(x, y) {
for (let dy = -2; dy <= 2; dy++) {
for (let dx = -2; dx <= 2; dx++)
this.setFunctionModule(x + dx, y + dy, Math.max(Math.abs(dx), Math.abs(dy)) != 1);
}
}
// Sets the color of a module and marks it as a function module.
// Only used by the constructor. Coordinates must be in bounds.
setFunctionModule(x, y, isDark) {
this.modules[y][x] = isDark;
this.isFunction[y][x] = true;
}
/*-- Private helper methods for constructor: Codewords and masking --*/
// Returns a new byte string representing the given data with the appropriate error correction
// codewords appended to it, based on this object's version and error correction level.
addEccAndInterleave(data) {
const ver = this.version;
const ecl = this.errorCorrectionLevel;
if (data.length != QrCode.getNumDataCodewords(ver, ecl))
throw new RangeError("Invalid argument");
// Calculate parameter numbers
const numBlocks = QrCode.NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal][ver];
const blockEccLen = QrCode.ECC_CODEWORDS_PER_BLOCK[ecl.ordinal][ver];
const rawCodewords = Math.floor(QrCode.getNumRawDataModules(ver) / 8);
const numShortBlocks = numBlocks - rawCodewords % numBlocks;
const shortBlockLen = Math.floor(rawCodewords / numBlocks);
// Split data into blocks and append ECC to each block
let blocks = [];
const rsDiv = QrCode.reedSolomonComputeDivisor(blockEccLen);
for (let i = 0, k = 0; i < numBlocks; i++) {
let dat = data.slice(k, k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1));
k += dat.length;
const ecc = QrCode.reedSolomonComputeRemainder(dat, rsDiv);
if (i < numShortBlocks)
dat.push(0);
blocks.push(dat.concat(ecc));
}
// Interleave (not concatenate) the bytes from every block into a single sequence
let result = [];
for (let i = 0; i < blocks[0].length; i++) {
blocks.forEach((block, j) => {
// Skip the padding byte in short blocks
if (i != shortBlockLen - blockEccLen || j >= numShortBlocks)
result.push(block[i]);
});
}
assert(result.length == rawCodewords);
return result;
}
// Draws the given sequence of 8-bit codewords (data and error correction) onto the entire
// data area of this QR Code. Function modules need to be marked off before this is called.
drawCodewords(data) {
if (data.length != Math.floor(QrCode.getNumRawDataModules(this.version) / 8))
throw new RangeError("Invalid argument");
let i = 0; // Bit index into the data
// Do the funny zigzag scan
for (let right = this.size - 1; right >= 1; right -= 2) { // Index of right column in each column pair
if (right == 6)
right = 5;
for (let vert = 0; vert < this.size; vert++) { // Vertical counter
for (let j = 0; j < 2; j++) {
const x = right - j; // Actual x coordinate
const upward = ((right + 1) & 2) == 0;
const y = upward ? this.size - 1 - vert : vert; // Actual y coordinate
if (!this.isFunction[y][x] && i < data.length * 8) {
this.modules[y][x] = getBit(data[i >>> 3], 7 - (i & 7));
i++;
}
// If this QR Code has any remainder bits (0 to 7), they were assigned as
// 0/false/light by the constructor and are left unchanged by this method
}
}
}
assert(i == data.length * 8);
}
// XORs the codeword modules in this QR Code with the given mask pattern.
// The function modules must be marked and the codeword bits must be drawn
// before masking. Due to the arithmetic of XOR, calling applyMask() with
// the same mask value a second time will undo the mask. A final well-formed
// QR Code needs exactly one (not zero, two, etc.) mask applied.
applyMask(mask) {
if (mask < 0 || mask > 7)
throw new RangeError("Mask value out of range");
for (let y = 0; y < this.size; y++) {
for (let x = 0; x < this.size; x++) {
let invert;
switch (mask) {
case 0:
invert = (x + y) % 2 == 0;
break;
case 1:
invert = y % 2 == 0;
break;
case 2:
invert = x % 3 == 0;
break;
case 3:
invert = (x + y) % 3 == 0;
break;
case 4:
invert = (Math.floor(x / 3) + Math.floor(y / 2)) % 2 == 0;
break;
case 5:
invert = x * y % 2 + x * y % 3 == 0;
break;
case 6:
invert = (x * y % 2 + x * y % 3) % 2 == 0;
break;
case 7:
invert = ((x + y) % 2 + x * y % 3) % 2 == 0;
break;
default: throw new Error("Unreachable");
}
if (!this.isFunction[y][x] && invert)
this.modules[y][x] = !this.modules[y][x];
}
}
}
// Calculates and returns the penalty score based on state of this QR Code's current modules.
// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score.
getPenaltyScore() {
let result = 0;
// Adjacent modules in row having same color, and finder-like patterns
for (let y = 0; y < this.size; y++) {
let runColor = false;
let runX = 0;
let runHistory = [0, 0, 0, 0, 0, 0, 0];
for (let x = 0; x < this.size; x++) {
if (this.modules[y][x] == runColor) {
runX++;
if (runX == 5)
result += QrCode.PENALTY_N1;
else if (runX > 5)
result++;
}
else {
this.finderPenaltyAddHistory(runX, runHistory);
if (!runColor)
result += this.finderPenaltyCountPatterns(runHistory) * QrCode.PENALTY_N3;
runColor = this.modules[y][x];
runX = 1;
}
}
result += this.finderPenaltyTerminateAndCount(runColor, runX, runHistory) * QrCode.PENALTY_N3;
}
// Adjacent modules in column having same color, and finder-like patterns
for (let x = 0; x < this.size; x++) {
let runColor = false;
let runY = 0;
let runHistory = [0, 0, 0, 0, 0, 0, 0];
for (let y = 0; y < this.size; y++) {
if (this.modules[y][x] == runColor) {
runY++;
if (runY == 5)
result += QrCode.PENALTY_N1;
else if (runY > 5)
result++;
}
else {
this.finderPenaltyAddHistory(runY, runHistory);
if (!runColor)
result += this.finderPenaltyCountPatterns(runHistory) * QrCode.PENALTY_N3;
runColor = this.modules[y][x];
runY = 1;
}
}
result += this.finderPenaltyTerminateAndCount(runColor, runY, runHistory) * QrCode.PENALTY_N3;
}
// 2*2 blocks of modules having same color
for (let y = 0; y < this.size - 1; y++) {
for (let x = 0; x < this.size - 1; x++) {
const color = this.modules[y][x];
if (color == this.modules[y][x + 1] &&
color == this.modules[y + 1][x] &&
color == this.modules[y + 1][x + 1])
result += QrCode.PENALTY_N2;
}
}
// Balance of dark and light modules
let dark = 0;
for (const row of this.modules)
dark = row.reduce((sum, color) => sum + (color ? 1 : 0), dark);
const total = this.size * this.size; // Note that size is odd, so dark/total != 1/2
// Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)%
const k = Math.ceil(Math.abs(dark * 20 - total * 10) / total) - 1;
assert(0 <= k && k <= 9);
result += k * QrCode.PENALTY_N4;
assert(0 <= result && result <= 2568888); // Non-tight upper bound based on default values of PENALTY_N1, ..., N4
return result;
}
/*-- Private helper functions --*/
// Returns an ascending list of positions of alignment patterns for this version number.
// Each position is in the range [0,177), and are used on both the x and y axes.
// This could be implemented as lookup table of 40 variable-length lists of integers.
getAlignmentPatternPositions() {
if (this.version == 1)
return [];
else {
const numAlign = Math.floor(this.version / 7) + 2;
const step = (this.version == 32) ? 26 :
Math.ceil((this.version * 4 + 4) / (numAlign * 2 - 2)) * 2;
let result = [6];
for (let pos = this.size - 7; result.length < numAlign; pos -= step)
result.splice(1, 0, pos);
return result;
}
}
// Returns the number of data bits that can be stored in a QR Code of the given version number, after
// all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8.
// The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table.
static getNumRawDataModules(ver) {
if (ver < QrCode.MIN_VERSION || ver > QrCode.MAX_VERSION)
throw new RangeError("Version number out of range");
let result = (16 * ver + 128) * ver + 64;
if (ver >= 2) {
const numAlign = Math.floor(ver / 7) + 2;
result -= (25 * numAlign - 10) * numAlign - 55;
if (ver >= 7)
result -= 36;
}
assert(208 <= result && result <= 29648);
return result;
}
// Returns the number of 8-bit data (i.e. not error correction) codewords contained in any
// QR Code of the given version number and error correction level, with remainder bits discarded.
// This stateless pure function could be implemented as a (40*4)-cell lookup table.
static getNumDataCodewords(ver, ecl) {
return Math.floor(QrCode.getNumRawDataModules(ver) / 8) -
QrCode.ECC_CODEWORDS_PER_BLOCK[ecl.ordinal][ver] *
QrCode.NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal][ver];
}
// Returns a Reed-Solomon ECC generator polynomial for the given degree. This could be
// implemented as a lookup table over all possible parameter values, instead of as an algorithm.
static reedSolomonComputeDivisor(degree) {
if (degree < 1 || degree > 255)
throw new RangeError("Degree out of range");
// Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1.
// For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array [255, 8, 93].
let result = [];
for (let i = 0; i < degree - 1; i++)
result.push(0);
result.push(1); // Start off with the monomial x^0
// Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}),
// and drop the highest monomial term which is always 1x^degree.
// Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D).
let root = 1;
for (let i = 0; i < degree; i++) {
// Multiply the current product by (x - r^i)
for (let j = 0; j < result.length; j++) {
result[j] = QrCode.reedSolomonMultiply(result[j], root);
if (j + 1 < result.length)
result[j] ^= result[j + 1];
}
root = QrCode.reedSolomonMultiply(root, 0x02);
}
return result;
}
// Returns the Reed-Solomon error correction codeword for the given data and divisor polynomials.
static reedSolomonComputeRemainder(data, divisor) {
let result = divisor.map(_ => 0);
for (const b of data) { // Polynomial division
const factor = b ^ result.shift();
result.push(0);
divisor.forEach((coef, i) => result[i] ^= QrCode.reedSolomonMultiply(coef, factor));
}
return result;
}
// Returns the product of the two given field elements modulo GF(2^8/0x11D). The arguments and result
// are unsigned 8-bit integers. This could be implemented as a lookup table of 256*256 entries of uint8.
static reedSolomonMultiply(x, y) {
if (x >>> 8 != 0 || y >>> 8 != 0)
throw new RangeError("Byte out of range");
// Russian peasant multiplication
let z = 0;
for (let i = 7; i >= 0; i--) {
z = (z << 1) ^ ((z >>> 7) * 0x11D);
z ^= ((y >>> i) & 1) * x;
}
assert(z >>> 8 == 0);
return z;
}
// Can only be called immediately after a light run is added, and
// returns either 0, 1, or 2. A helper function for getPenaltyScore().
finderPenaltyCountPatterns(runHistory) {
const n = runHistory[1];
assert(n <= this.size * 3);
const core = n > 0 && runHistory[2] == n && runHistory[3] == n * 3 && runHistory[4] == n && runHistory[5] == n;
return (core && runHistory[0] >= n * 4 && runHistory[6] >= n ? 1 : 0)
+ (core && runHistory[6] >= n * 4 && runHistory[0] >= n ? 1 : 0);
}
// Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore().
finderPenaltyTerminateAndCount(currentRunColor, currentRunLength, runHistory) {
if (currentRunColor) { // Terminate dark run
this.finderPenaltyAddHistory(currentRunLength, runHistory);
currentRunLength = 0;
}
currentRunLength += this.size; // Add light border to final run
this.finderPenaltyAddHistory(currentRunLength, runHistory);
return this.finderPenaltyCountPatterns(runHistory);
}
// Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore().
finderPenaltyAddHistory(currentRunLength, runHistory) {
if (runHistory[0] == 0)
currentRunLength += this.size; // Add light border to initial run
runHistory.pop();
runHistory.unshift(currentRunLength);
}
}
/*-- Constants and tables --*/
// The minimum version number supported in the QR Code Model 2 standard.
QrCode.MIN_VERSION = 1;
// The maximum version number supported in the QR Code Model 2 standard.
QrCode.MAX_VERSION = 40;
// For use in getPenaltyScore(), when evaluating which mask is best.
QrCode.PENALTY_N1 = 3;
QrCode.PENALTY_N2 = 3;
QrCode.PENALTY_N3 = 40;
QrCode.PENALTY_N4 = 10;
QrCode.ECC_CODEWORDS_PER_BLOCK = [
// Version: (note that index 0 is for padding, and is set to an illegal value)
//0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
[-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],
[-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28],
[-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],
[-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], // High
];
QrCode.NUM_ERROR_CORRECTION_BLOCKS = [
// Version: (note that index 0 is for padding, and is set to an illegal value)
//0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
[-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25],
[-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49],
[-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68],
[-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81], // High
];
qrcodegen.QrCode = QrCode;
// Appends the given number of low-order bits of the given value
// to the given buffer. Requires 0 <= len <= 31 and 0 <= val < 2^len.
function appendBits(val, len, bb) {
if (len < 0 || len > 31 || val >>> len != 0)
throw new RangeError("Value out of range");
for (let i = len - 1; i >= 0; i--) // Append bit by bit
bb.push((val >>> i) & 1);
}
// Returns true iff the i'th bit of x is set to 1.
function getBit(x, i) {
return ((x >>> i) & 1) != 0;
}
// Throws an exception if the given condition is false.
function assert(cond) {
if (!cond)
throw new Error("Assertion error");
}
/*---- Data segment class ----*/
/*
* A segment of character/binary/control data in a QR Code symbol.
* Instances of this class are immutable.
* The mid-level way to create a segment is to take the payload data
* and call a static factory function such as QrSegment.makeNumeric().
* The low-level way to create a segment is to custom-make the bit buffer
* and call the QrSegment() constructor with appropriate values.
* This segment class imposes no length restrictions, but QR Codes have restrictions.
* Even in the most favorable conditions, a QR Code can only hold 7089 characters of data.
* Any segment longer than this is meaningless for the purpose of generating QR Codes.
*/
class QrSegment {
/*-- Constructor (low level) and fields --*/
// Creates a new QR Code segment with the given attributes and data.
// The character count (numChars) must agree with the mode and the bit buffer length,
// but the constraint isn't checked. The given bit buffer is cloned and stored.
constructor(
// The mode indicator of this segment.
mode,
// The length of this segment's unencoded data. Measured in characters for
// numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode.
// Always zero or positive. Not the same as the data's bit length.
numChars,
// The data bits of this segment. Accessed through getData().
bitData) {
this.mode = mode;
this.numChars = numChars;
this.bitData = bitData;
if (numChars < 0)
throw new RangeError("Invalid argument");
this.bitData = bitData.slice(); // Make defensive copy
}
/*-- Static factory functions (mid level) --*/
// Returns a segment representing the given binary data encoded in
// byte mode. All input byte arrays are acceptable. Any text string
// can be converted to UTF-8 bytes and encoded as a byte mode segment.
static makeBytes(data) {
let bb = [];
for (const b of data)
appendBits(b, 8, bb);
return new QrSegment(QrSegment.Mode.BYTE, data.length, bb);
}
// Returns a segment representing the given string of decimal digits encoded in numeric mode.
static makeNumeric(digits) {
if (!QrSegment.isNumeric(digits))
throw new RangeError("String contains non-numeric characters");
let bb = [];
for (let i = 0; i < digits.length;) { // Consume up to 3 digits per iteration
const n = Math.min(digits.length - i, 3);
appendBits(parseInt(digits.substr(i, n), 10), n * 3 + 1, bb);
i += n;
}
return new QrSegment(QrSegment.Mode.NUMERIC, digits.length, bb);
}
// Returns a segment representing the given text string encoded in alphanumeric mode.
// The characters allowed are: 0 to 9, A to Z (uppercase only), space,
// dollar, percent, asterisk, plus, hyphen, period, slash, colon.
static makeAlphanumeric(text) {
if (!QrSegment.isAlphanumeric(text))
throw new RangeError("String contains unencodable characters in alphanumeric mode");
let bb = [];
let i;
for (i = 0; i + 2 <= text.length; i += 2) { // Process groups of 2
let temp = QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45;
temp += QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1));
appendBits(temp, 11, bb);
}
if (i < text.length) // 1 character remaining
appendBits(QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6, bb);
return new QrSegment(QrSegment.Mode.ALPHANUMERIC, text.length, bb);
}
// Returns a new mutable list of zero or more segments to represent the given Unicode text string.
// The result may use various segment modes and switch modes to optimize the length of the bit stream.
static makeSegments(text) {
// Select the most efficient segment encoding automatically
if (text == "")
return [];
else if (QrSegment.isNumeric(text))
return [QrSegment.makeNumeric(text)];
else if (QrSegment.isAlphanumeric(text))
return [QrSegment.makeAlphanumeric(text)];
else
return [QrSegment.makeBytes(QrSegment.toUtf8ByteArray(text))];
}
// Returns a segment representing an Extended Channel Interpretation
// (ECI) designator with the given assignment value.
static makeEci(assignVal) {
let bb = [];
if (assignVal < 0)
throw new RangeError("ECI assignment value out of range");
else if (assignVal < (1 << 7))
appendBits(assignVal, 8, bb);
else if (assignVal < (1 << 14)) {
appendBits(0b10, 2, bb);
appendBits(assignVal, 14, bb);
}
else if (assignVal < 1000000) {
appendBits(0b110, 3, bb);
appendBits(assignVal, 21, bb);
}
else
throw new RangeError("ECI assignment value out of range");
return new QrSegment(QrSegment.Mode.ECI, 0, bb);
}
// Tests whether the given string can be encoded as a segment in numeric mode.
// A string is encodable iff each character is in the range 0 to 9.
static isNumeric(text) {
return QrSegment.NUMERIC_REGEX.test(text);
}
// Tests whether the given string can be encoded as a segment in alphanumeric mode.
// A string is encodable iff each character is in the following set: 0 to 9, A to Z
// (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon.
static isAlphanumeric(text) {
return QrSegment.ALPHANUMERIC_REGEX.test(text);
}
/*-- Methods --*/
// Returns a new copy of the data bits of this segment.
getData() {
return this.bitData.slice(); // Make defensive copy
}
// (Package-private) Calculates and returns the number of bits needed to encode the given segments at
// the given version. The result is infinity if a segment has too many characters to fit its length field.
static getTotalBits(segs, version) {
let result = 0;
for (const seg of segs) {
const ccbits = seg.mode.numCharCountBits(version);
if (seg.numChars >= (1 << ccbits))
return Infinity; // The segment's length doesn't fit the field's bit width
result += 4 + ccbits + seg.bitData.length;
}
return result;
}
// Returns a new array of bytes representing the given string encoded in UTF-8.
static toUtf8ByteArray(str) {
str = encodeURI(str);
let result = [];
for (let i = 0; i < str.length; i++) {
if (str.charAt(i) != "%")
result.push(str.charCodeAt(i));
else {
result.push(parseInt(str.substr(i + 1, 2), 16));
i += 2;
}
}
return result;
}
}
/*-- Constants --*/
// Describes precisely all strings that are encodable in numeric mode.
QrSegment.NUMERIC_REGEX = /^[0-9]*$/;
// Describes precisely all strings that are encodable in alphanumeric mode.
QrSegment.ALPHANUMERIC_REGEX = /^[A-Z0-9 $%*+.\/:-]*$/;
// The set of all legal characters in alphanumeric mode,
// where each character value maps to the index in the string.
QrSegment.ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
qrcodegen.QrSegment = QrSegment;
})(qrcodegen || (qrcodegen = {}));
/*---- Public helper enumeration ----*/
(function (qrcodegen) {
var QrCode;
(function (QrCode) {
/*
* The error correction level in a QR Code symbol. Immutable.
*/
class Ecc {
/*-- Constructor and fields --*/
constructor(
// In the range 0 to 3 (unsigned 2-bit integer).
ordinal,
// (Package-private) In the range 0 to 3 (unsigned 2-bit integer).
formatBits) {
this.ordinal = ordinal;
this.formatBits = formatBits;
}
}
/*-- Constants --*/
Ecc.LOW = new Ecc(0, 1); // The QR Code can tolerate about 7% erroneous codewords
Ecc.MEDIUM = new Ecc(1, 0); // The QR Code can tolerate about 15% erroneous codewords
Ecc.QUARTILE = new Ecc(2, 3); // The QR Code can tolerate about 25% erroneous codewords
Ecc.HIGH = new Ecc(3, 2); // The QR Code can tolerate about 30% erroneous codewords
QrCode.Ecc = Ecc;
})(QrCode = qrcodegen.QrCode || (qrcodegen.QrCode = {}));
})(qrcodegen || (qrcodegen = {}));
/*---- Public helper enumeration ----*/
(function (qrcodegen) {
var QrSegment;
(function (QrSegment) {
/*
* Describes how a segment's data bits are interpreted. Immutable.
*/
class Mode {
/*-- Constructor and fields --*/
constructor(
// The mode indicator bits, which is a uint4 value (range 0 to 15).
modeBits,
// Number of character count bits for three different version ranges.
numBitsCharCount) {
this.modeBits = modeBits;
this.numBitsCharCount = numBitsCharCount;
}
/*-- Method --*/
// (Package-private) Returns the bit width of the character count field for a segment in
// this mode in a QR Code at the given version number. The result is in the range [0, 16].
numCharCountBits(ver) {
return this.numBitsCharCount[Math.floor((ver + 7) / 17)];
}
}
/*-- Constants --*/
Mode.NUMERIC = new Mode(0x1, [10, 12, 14]);
Mode.ALPHANUMERIC = new Mode(0x2, [9, 11, 13]);
Mode.BYTE = new Mode(0x4, [8, 16, 16]);
Mode.KANJI = new Mode(0x8, [8, 10, 12]);
Mode.ECI = new Mode(0x7, [0, 0, 0]);
QrSegment.Mode = Mode;
})(QrSegment = qrcodegen.QrSegment || (qrcodegen.QrSegment = {}));
})(qrcodegen || (qrcodegen = {}));

BIN
Web/public/png/android-chrome-192x192.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Web/public/png/android-chrome-512x512.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Web/public/png/logo-wordmark.png (Stored with Git LFS) Normal file

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more