From 64a517333b40389c2d3aa2a5fa9419b159d9377d Mon Sep 17 00:00:00 2001
From: neon443 <69979447+neon443@users.noreply.github.com>
Date: Sun, 1 Dec 2024 11:18:15 +0000
Subject: [PATCH] Rewrote basically half the app + reamde + noDebug.xcscheme +
ui improvements +max die is 100+overflow protextion +fix giant padding in
diceview +rewrite rng2() +ui friedlification +rewrite arrCombine
---
README.md | 8 ++
.../xcschemes/RNG-noDebug.xcscheme | 78 +++++++++++++
RNG/ContentView.swift | 75 ++++++------
RNG/DiceView.swift | 71 +++++++-----
RNG/NumberView.swift | 108 +++++-------------
RNG/PasswordView.swift | 69 +++++------
RNG/RNGApp.swift | 21 ++--
7 files changed, 236 insertions(+), 194 deletions(-)
create mode 100644 README.md
create mode 100644 RNG.xcodeproj/xcshareddata/xcschemes/RNG-noDebug.xcscheme
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c0fbe67
--- /dev/null
+++ b/README.md
@@ -0,0 +1,8 @@
+# RNG_Swift
+
+A fully featured Randomizer written in Swift with UI in SwiftUI!
+
+## Features
+- Number generator
+- Password generator
+- Die Generator
\ No newline at end of file
diff --git a/RNG.xcodeproj/xcshareddata/xcschemes/RNG-noDebug.xcscheme b/RNG.xcodeproj/xcshareddata/xcschemes/RNG-noDebug.xcscheme
new file mode 100644
index 0000000..7361d06
--- /dev/null
+++ b/RNG.xcodeproj/xcshareddata/xcschemes/RNG-noDebug.xcscheme
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/RNG/ContentView.swift b/RNG/ContentView.swift
index 6d2721d..d9aee3e 100644
--- a/RNG/ContentView.swift
+++ b/RNG/ContentView.swift
@@ -12,44 +12,46 @@ struct ContentView: View {
VStack {
NavigationSplitView {
List {
- NavigationLink {
- NumberView()
- .navigationTitle("Random Number Generator")
- } label: {
- HStack {
- Text("Random Number Generator")
- Spacer()
- Image(systemName: "textformat.123")
- }
- }
- NavigationLink {
- DiceView()
- .navigationTitle("Dice")
- } label: {
- HStack {
- Text("Dice")
- Spacer()
- Image(systemName: "die.face.1")
- Image(systemName: "die.face.2.fill")
- Image(systemName: "die.face.3")
- Image(systemName: "die.face.4.fill")
- Image(systemName: "die.face.5")
- Image(systemName: "die.face.6.fill")
- }
- }
- NavigationLink {
- PasswordView()
- .navigationTitle("Password")
- } label: {
- HStack {
- Text("Password")
- Spacer()
- Image(systemName: "rectangle.and.pencil.and.ellipsis")
+ Section("Generate...") {
+ NavigationLink {
+ NumberView()
+ .navigationTitle("Numbers")
+ } label: {
+ HStack {
+ Text("Numbers")
+ Spacer()
+ Image(systemName: "textformat.123")
+ }
+ }
+ NavigationLink {
+ DiceView()
+ .navigationTitle("Die")
+ } label: {
+ HStack {
+ Text("Die")
+ Spacer()
+ Image(systemName: "die.face.1")
+ Image(systemName: "die.face.2.fill")
+ Image(systemName: "die.face.3")
+ Image(systemName: "die.face.4.fill")
+ Image(systemName: "die.face.5")
+ Image(systemName: "die.face.6.fill")
+ }
+ }
+ NavigationLink {
+ PasswordView()
+ .navigationTitle("Passwords")
+ } label: {
+ HStack {
+ Text("Passwords")
+ Spacer()
+ Image(systemName: "rectangle.and.pencil.and.ellipsis")
+ }
}
}
+ .navigationTitle("RNG")
+ .navigationBarTitleDisplayMode(.inline)
}
- .navigationTitle("RNG")
- .navigationBarTitleDisplayMode(.inline)
} detail: {
Image(systemName: "dice.fill")
}
@@ -57,3 +59,6 @@ struct ContentView: View {
}
}
+#Preview {
+ ContentView()
+}
diff --git a/RNG/DiceView.swift b/RNG/DiceView.swift
index 5b955a3..598a391 100644
--- a/RNG/DiceView.swift
+++ b/RNG/DiceView.swift
@@ -8,26 +8,36 @@
import SwiftUI
struct DiceView: View {
- @State var generated: [Int] = [0]
+ @State var advanced: Bool = false
+ @State var generated: [Int] = []
@State var displayDies: [Int] = []
@State var displayMultiDieMode = ""
@State var multiDieMode = "plus"
- @State var result = 0
+ @State var result: UInt = 0
@State var resultDescription = ""
- @State var history: [Int] = []
let columns = [GridItem(.adaptive(minimum: 25, maximum: 75))]
@State var dies: Double = 2
+
var body: some View {
VStack {
List {
Section("Number of die") {
+ Toggle(isOn: $advanced) {
+ Text("Advanced Mode")
+ }
HStack {
- Text( String( Int(dies) ) )
- .font(.system(size: 25, weight: .bold))
+ Text(String(Int(dies)))
+ .font(.system(size: 20, weight: .heavy))
+ .frame(width: ((dies > 99) ? 40 : (dies > 9) ? 30 : 20))
Divider()
Text("1")
- Slider(value: $dies, in: 1...20, step: 1)
- Text("20")
+ if advanced {
+ Slider(value: $dies, in: 1...100, step: 1)
+ Text("100")
+ } else {
+ Slider(value: $dies, in: 1...20, step: 1)
+ Text("20")
+ }
}
}
Section("Multi die mode") {
@@ -37,36 +47,36 @@ struct DiceView: View {
}.pickerStyle(SegmentedPickerStyle())
}
Section("Visual") {
- HStack {
- Spacer()
- if displayDies.isEmpty {
- Text("Results are visualised here when you press the generate button")
- .font(.subheadline)
- } else {
- LazyVGrid(columns: columns, spacing: 10) {
- ForEach(0.. String {
var result = ""
var symbol = ""
if inp.isEmpty {
- return "0"
+ return ""
} else {
if combineMode == "plus" {
- symbol = " + "
+ symbol = "+"
} else if combineMode == "multiply" {
- symbol = " x "
+ symbol = "x"
}
for i in 0...len {
if i == len {
@@ -104,7 +114,6 @@ func describeResult(inp: [Int], combineMode: String) -> String {
result += String(inp[i]) + symbol
}
}
- result += " = " + String(arrCombine(arr: inp, combineMode: combineMode))
return result
}
}
diff --git a/RNG/NumberView.swift b/RNG/NumberView.swift
index 7371f74..30d150c 100644
--- a/RNG/NumberView.swift
+++ b/RNG/NumberView.swift
@@ -5,36 +5,17 @@
// Created by Nihaal on 09/10/2024.
//
-
-
-
-
-
-
-
-
-
-//fix date created
-//TODO: readd ios 16 support
-//TODO: try to use inject
-
-
-
-
-
-
-
import SwiftUI
struct NumberView: View {
@State var low: String = "1"
@State var high: String = "10"
@State var exclude: String = "none"
- @State var generated = "5"
+ @State var generated = ""
@State var prevGen = ""
@State var generatedInt: Int = 0
@State var prevGenInt: Int = 0
- @State var dispResult = 5
+ @State var dispResult = 0
var body: some View {
List {
HStack {
@@ -65,30 +46,18 @@ struct NumberView: View {
}
Section("Description") {
Text(describeInputs(min: low, max: high, exclude: exclude))
+ .font(.headline)
+ .fontWeight(.heavy)
+ .frame(alignment: .center)
}
}
- Text(String(dispResult))
- .font(.system(size: 75, weight: .bold))
+ Text(generated)
+ .font(.system(size: 50, weight: .bold))
.foregroundColor(.gray)
- .frame(height: 50)
+ .frame(height: 40)
Button {
prevGen = generated
- generated = rng2(min: low, max: high, exclude: exclude)
- prevGenInt = Int(prevGen)!
- generatedInt = Int(generated)!
- if prevGenInt < generatedInt {
- for _ in prevGenInt...generatedInt {
- dispResult += 1
- //sleep( UInt32( 1 / (generatedInt - prevGenInt) ) )
- }
- } else if prevGenInt > generatedInt {
- for _ in generatedInt...prevGenInt {
- dispResult -= 1
- //sleep( UInt32( 1 / (prevGenInt - generatedInt) ) )
- }
- } else if prevGenInt == generatedInt {
- dispResult = generatedInt
- }
+ generated = rng3(min: low, max: high, exclude: exclude)
} label: {
Text("Generate")
.padding(.horizontal)
@@ -96,26 +65,26 @@ struct NumberView: View {
}
.buttonStyle(BorderedProminentButtonStyle())
.cornerRadius(15)
- .padding(.bottom)
+ .padding(.vertical)
}
}
func describeInputs(min: String, max: String, exclude: String) -> String {
- let validExcludes = ["start", "end", "both", "none"]
+ let validExcludes = ["start", "none", "end", "both"]
guard validExcludes.contains(exclude) else {
print("invalid exclude: " + exclude)
return "invalid exclude: " + exclude
}
var result = "Any number from "
- result += min != "" ? min : "_"
+ result += min
result += " to "
- result += max != "" ? max : "_"
+ result += max
if min == "" || max == "" {
return "Enter values above."
- } else {
- switch exclude {
+ }
+ switch exclude {
case "start":
result += ", excluding \(min)"
case "end":
@@ -126,48 +95,31 @@ func describeInputs(min: String, max: String, exclude: String) -> String {
break
default:
result = "invalid 'exclude'"
- }
}
- result += "."
- return result
+ return result + "."
}
-enum rng2Errors: Error {
- case h
-}
-
-func rng2(min: String, max: String, exclude: String) -> String {
- guard min != "" || max != "" else {
- return "Enter values above."
+func rng3(min: String, max: String, exclude: String) -> String {
+ var newMin = Int(min)!
+ var newMax = Int(max)!
+ guard newMin <= newMax else {
+ return "Invalid inputs"
}
- guard var minInt = Int(min) else {
- print("invalid min")
- return "-1"
+ guard newMin != newMax else {
+ return "No numbers"
}
- guard var maxInt = Int(max), maxInt >= minInt else {
- print("invalid max or is less than min")
- return "-1"
+ guard newMin + 1 != newMax else {
+ return "No numbers"
}
- guard exclude != "both", min != max else {
- print("excluding both but min == max")
- return "No possible numbers, both bounds equal."
- }
- let minIntPlus1 = minInt + 1
- guard exclude != "both", minIntPlus1 != maxInt else {
- print("excluding both but min +1 == max")
- return "No possible numbers."
- }
- var generated = 0
if exclude == "both" {
- maxInt -= 1
- minInt += 1
+ newMax -= 1
+ newMin += 1
} else if exclude == "start" {
- minInt += 1
+ newMin += 1
} else if exclude == "end" {
- maxInt -= 1
+ newMax -= 1
}
- generated = rng(min: minInt, max: maxInt)
- return String(generated)
+ return String(rng(min: newMin, max: newMax))
}
#Preview {
diff --git a/RNG/PasswordView.swift b/RNG/PasswordView.swift
index 2c6807c..af7dc55 100644
--- a/RNG/PasswordView.swift
+++ b/RNG/PasswordView.swift
@@ -10,12 +10,12 @@ import SwiftUI
struct PasswordView: View {
@State var selectedOptions: [PassOption] = []
let options: [PassOption] = [
- PassOption(name: "0-9", chars: Array("0123456789")),
- PassOption(name: "a-z", chars: Array("abcdefghijklmnopqrstuvwxyz")),
- PassOption(name: "A-Z", chars: Array("ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
+ PassOption(name: "Digits", chars: Array("0123456789")),
+ PassOption(name: "Lowercase characters", chars: Array("abcdefghijklmnopqrstuvwxyz")),
+ PassOption(name: "Uppercase characters", chars: Array("ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
]
@State var presetLen = 4
- @State var customLen = 8
+ @State var customLen: Int = 0
@State var generated = ""
@State var result = ""
@State var history: [Int] = []
@@ -23,16 +23,6 @@ struct PasswordView: View {
var body: some View {
VStack {
List {
- Text("Hello, world!")
- .font(.largeTitle)
- .foregroundColor(.white)
- .padding()
- .background(Color.blue)
- .padding()
- .background(Color.mint)
- .padding()
- .background(Color.green)
-
Section("Include") {
ForEach(options) { option in
Toggle(isOn: Binding(
@@ -59,35 +49,30 @@ struct PasswordView: View {
Text("Custom: \(customLen)").tag(-1)
}
.pickerStyle(SegmentedPickerStyle())
+
+ if presetLen == -1 {
+ TextField("Custom", value: $customLen, formatter: NumberFormatter())
+ .keyboardType(.numberPad)
+ .frame(width: 50)
+ }
}
-
- if presetLen == -1 {
- TextField("Custom", value: $customLen, formatter: NumberFormatter())
- .keyboardType(.numberPad)
- .frame(width: 50)
- }
-
- Text(String(result))
- .font(.system(size: 75, weight: .bold))
- .foregroundColor(.gray)
- .frame(height: 50)
-
- Text(String(generated))
- .font(.system(size: 75, weight: .bold))
- .foregroundColor(.gray)
- .frame(height: 50)
-
- Button {
- generated = genPass(selectdOpts: selectedOptions, len: (presetLen == -1 ? customLen : presetLen))
- } label: {
- Text("Generate")
- .padding(.horizontal)
- .font(.system(size: 25, weight: .bold))
- }
- .buttonStyle(BorderedProminentButtonStyle())
- .cornerRadius(15)
- .padding(.vertical)
}
+
+ Text(String(generated))
+ .font(.system(size: 50, weight: .bold))
+ .foregroundColor(.gray)
+ .frame(height: 40)
+
+ Button {
+ generated = genPass(selectdOpts: selectedOptions, len: (presetLen == -1 ? customLen : presetLen))
+ } label: {
+ Text("Generate")
+ .padding(.horizontal)
+ .font(.system(size: 25, weight: .bold))
+ }
+ .buttonStyle(BorderedProminentButtonStyle())
+ .cornerRadius(15)
+ .padding(.vertical)
}
}
}
@@ -103,7 +88,7 @@ struct PassOption: Identifiable {
}
func genPass(selectdOpts: [PassOption], len: Int) -> String {
- let characters = selectdOpts.flatMap { $0.chars }
+ let characters = selectdOpts.flatMap { $0.chars }
guard !(characters.isEmpty) else {
print("characters empty")
diff --git a/RNG/RNGApp.swift b/RNG/RNGApp.swift
index dfc8044..aeddae9 100644
--- a/RNG/RNGApp.swift
+++ b/RNG/RNGApp.swift
@@ -35,15 +35,22 @@ func totalDoubleArr(arr: [Double]) -> Double {
}
// array combiner, adds or multiplies all ints in an array
-func arrCombine(arr: [Int], combineMode: String) -> Int {
- var output = 0
+func arrCombine(arr: [Int], combineMode: String) -> UInt {
+ var newArr: [UInt] = []
+ for i in 0...(arr.count-1) {
+ newArr.append(UInt(arr[i]))
+ }
+ var output: UInt = 0
if combineMode == "plus" {
- for num in arr {
+ for num in newArr {
output += num
}
} else if combineMode == "multiply" {
output = 1
- for num in arr {
+ for num in newArr {
+ guard output <= UInt.max / num else {
+ return UInt.max //cap at uint.max 2^64
+ }
output *= num
}
} else {
@@ -53,11 +60,8 @@ func arrCombine(arr: [Int], combineMode: String) -> Int {
return output
}
-
func rng(min: Int, max: Int) -> Int {
- var rng = 0
- rng = Int.random(in: min...max)
- return rng
+ return Int.random(in: min...max)
}
func rng6Die() -> Int {
@@ -69,6 +73,7 @@ func rngCDie(min: Int, max: Int) -> Int {
}
func rngN6DieArr(dies: Int) -> [Int] {
+ guard dies > 0 else { return [] }
var output: [Int] = []
for _ in 1...dies {
output.append(rng6Die())