Compare commits
13 commits
release/v0
...
main
Author | SHA1 | Date | |
---|---|---|---|
eeb17a1d50 | |||
9d9f951e9d | |||
970303d5ec | |||
3690f96e42 | |||
45fdf40af2 | |||
0ae58c67fa | |||
b3f189aa94 | |||
8c33834975 | |||
499782924f | |||
6a9c9a4533 | |||
af5ee82bd0 | |||
866764e1ab | |||
1c7e301fd8 |
39 changed files with 1223 additions and 96 deletions
12
PersonaForge.Blazor/App.razor
Normal file
12
PersonaForge.Blazor/App.razor
Normal file
|
@ -0,0 +1,12 @@
|
|||
<Router AppAssembly="@typeof(App).Assembly">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
|
||||
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
|
||||
</Found>
|
||||
<NotFound>
|
||||
<PageTitle>Not found</PageTitle>
|
||||
<LayoutView Layout="@typeof(MainLayout)">
|
||||
<p role="alert">Sorry, there's nothing at this address.</p>
|
||||
</LayoutView>
|
||||
</NotFound>
|
||||
</Router>
|
16
PersonaForge.Blazor/Layout/MainLayout.razor
Normal file
16
PersonaForge.Blazor/Layout/MainLayout.razor
Normal file
|
@ -0,0 +1,16 @@
|
|||
@inherits LayoutComponentBase
|
||||
<div class="page">
|
||||
<div class="sidebar">
|
||||
<NavMenu />
|
||||
</div>
|
||||
|
||||
<main>
|
||||
<div class="top-row px-4">
|
||||
<a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
|
||||
</div>
|
||||
|
||||
<article class="content px-4">
|
||||
@Body
|
||||
</article>
|
||||
</main>
|
||||
</div>
|
77
PersonaForge.Blazor/Layout/MainLayout.razor.css
Normal file
77
PersonaForge.Blazor/Layout/MainLayout.razor.css
Normal file
|
@ -0,0 +1,77 @@
|
|||
.page {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
|
||||
}
|
||||
|
||||
.top-row {
|
||||
background-color: #f7f7f7;
|
||||
border-bottom: 1px solid #d6d5d5;
|
||||
justify-content: flex-end;
|
||||
height: 3.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.top-row ::deep a, .top-row ::deep .btn-link {
|
||||
white-space: nowrap;
|
||||
margin-left: 1.5rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.top-row ::deep a:first-child {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@media (max-width: 640.98px) {
|
||||
.top-row {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.top-row ::deep a, .top-row ::deep .btn-link {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 641px) {
|
||||
.page {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 250px;
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.top-row {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.top-row.auth ::deep a:first-child {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.top-row, article {
|
||||
padding-left: 2rem !important;
|
||||
padding-right: 1.5rem !important;
|
||||
}
|
||||
}
|
39
PersonaForge.Blazor/Layout/NavMenu.razor
Normal file
39
PersonaForge.Blazor/Layout/NavMenu.razor
Normal file
|
@ -0,0 +1,39 @@
|
|||
<div class="top-row ps-3 navbar navbar-dark">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="">PersonaForge.Blazor</a>
|
||||
<button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="@NavMenuCssClass nav-scrollable" @onclick="ToggleNavMenu">
|
||||
<nav class="flex-column">
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
|
||||
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="counter">
|
||||
<span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> Counter
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="weather">
|
||||
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Weather
|
||||
</NavLink>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private bool collapseNavMenu = true;
|
||||
|
||||
private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;
|
||||
|
||||
private void ToggleNavMenu()
|
||||
{
|
||||
collapseNavMenu = !collapseNavMenu;
|
||||
}
|
||||
}
|
83
PersonaForge.Blazor/Layout/NavMenu.razor.css
Normal file
83
PersonaForge.Blazor/Layout/NavMenu.razor.css
Normal file
|
@ -0,0 +1,83 @@
|
|||
.navbar-toggler {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.top-row {
|
||||
height: 3.5rem;
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.bi {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
margin-right: 0.75rem;
|
||||
top: -1px;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.bi-house-door-fill-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.bi-plus-square-fill-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.bi-list-nested-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
font-size: 0.9rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.nav-item:first-of-type {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.nav-item:last-of-type {
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.nav-item ::deep a {
|
||||
color: #d7d7d7;
|
||||
border-radius: 4px;
|
||||
height: 3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 3rem;
|
||||
}
|
||||
|
||||
.nav-item ::deep a.active {
|
||||
background-color: rgba(255,255,255,0.37);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nav-item ::deep a:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
color: white;
|
||||
}
|
||||
|
||||
@media (min-width: 641px) {
|
||||
.navbar-toggler {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.collapse {
|
||||
/* Never collapse the sidebar for wide screens */
|
||||
display: block;
|
||||
}
|
||||
|
||||
.nav-scrollable {
|
||||
/* Allow sidebar to scroll for tall menus */
|
||||
height: calc(100vh - 3.5rem);
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
18
PersonaForge.Blazor/Pages/Counter.razor
Normal file
18
PersonaForge.Blazor/Pages/Counter.razor
Normal file
|
@ -0,0 +1,18 @@
|
|||
@page "/counter"
|
||||
|
||||
<PageTitle>Counter</PageTitle>
|
||||
|
||||
<h1>Counter</h1>
|
||||
|
||||
<p role="status">Current count: @currentCount</p>
|
||||
|
||||
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
|
||||
|
||||
@code {
|
||||
private int currentCount = 0;
|
||||
|
||||
private void IncrementCount()
|
||||
{
|
||||
currentCount++;
|
||||
}
|
||||
}
|
7
PersonaForge.Blazor/Pages/Home.razor
Normal file
7
PersonaForge.Blazor/Pages/Home.razor
Normal file
|
@ -0,0 +1,7 @@
|
|||
@page "/"
|
||||
|
||||
<PageTitle>Home</PageTitle>
|
||||
|
||||
<h1>Hello, world!</h1>
|
||||
|
||||
Welcome to your new app.
|
57
PersonaForge.Blazor/Pages/Sikms2Craft.razor
Normal file
57
PersonaForge.Blazor/Pages/Sikms2Craft.razor
Normal file
|
@ -0,0 +1,57 @@
|
|||
@page "/craft"
|
||||
@inject HttpClient Http
|
||||
|
||||
<PageTitle>Sims2Craft</PageTitle>
|
||||
|
||||
<h1>Craft</h1>
|
||||
|
||||
<p>This component demonstrates fetching data from the server.</p>
|
||||
|
||||
@if (forecasts == null)
|
||||
{
|
||||
<p><em>Loading...</em></p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Temp. (C)</th>
|
||||
<th>Temp. (F)</th>
|
||||
<th>Summary</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var forecast in forecasts)
|
||||
{
|
||||
<tr>
|
||||
<td>@forecast.Date.ToShortDateString()</td>
|
||||
<td>@forecast.TemperatureC</td>
|
||||
<td>@forecast.TemperatureF</td>
|
||||
<td>@forecast.Summary</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
|
||||
@code {
|
||||
private WeatherForecast[]? forecasts;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/weather.json");
|
||||
}
|
||||
|
||||
public class WeatherForecast
|
||||
{
|
||||
public DateOnly Date { get; set; }
|
||||
|
||||
public int TemperatureC { get; set; }
|
||||
|
||||
public string? Summary { get; set; }
|
||||
|
||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||
}
|
||||
}
|
57
PersonaForge.Blazor/Pages/Weather.razor
Normal file
57
PersonaForge.Blazor/Pages/Weather.razor
Normal file
|
@ -0,0 +1,57 @@
|
|||
@page "/weather"
|
||||
@inject HttpClient Http
|
||||
|
||||
<PageTitle>Weather</PageTitle>
|
||||
|
||||
<h1>Weather</h1>
|
||||
|
||||
<p>This component demonstrates fetching data from the server.</p>
|
||||
|
||||
@if (forecasts == null)
|
||||
{
|
||||
<p><em>Loading...</em></p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Temp. (C)</th>
|
||||
<th>Temp. (F)</th>
|
||||
<th>Summary</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var forecast in forecasts)
|
||||
{
|
||||
<tr>
|
||||
<td>@forecast.Date.ToShortDateString()</td>
|
||||
<td>@forecast.TemperatureC</td>
|
||||
<td>@forecast.TemperatureF</td>
|
||||
<td>@forecast.Summary</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
|
||||
@code {
|
||||
private WeatherForecast[]? forecasts;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/weather.json");
|
||||
}
|
||||
|
||||
public class WeatherForecast
|
||||
{
|
||||
public DateOnly Date { get; set; }
|
||||
|
||||
public int TemperatureC { get; set; }
|
||||
|
||||
public string? Summary { get; set; }
|
||||
|
||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||
}
|
||||
}
|
18
PersonaForge.Blazor/PersonaForge.Blazor.csproj
Normal file
18
PersonaForge.Blazor/PersonaForge.Blazor.csproj
Normal file
|
@ -0,0 +1,18 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.0" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\PersonaForge\PersonaForge.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
11
PersonaForge.Blazor/Program.cs
Normal file
11
PersonaForge.Blazor/Program.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||
using PersonaForge.Blazor;
|
||||
|
||||
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
||||
builder.RootComponents.Add<App>("#app");
|
||||
builder.RootComponents.Add<HeadOutlet>("head::after");
|
||||
|
||||
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
|
||||
|
||||
await builder.Build().RunAsync();
|
41
PersonaForge.Blazor/Properties/launchSettings.json
Normal file
41
PersonaForge.Blazor/Properties/launchSettings.json
Normal file
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:55547",
|
||||
"sslPort": 44325
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
|
||||
"applicationUrl": "http://localhost:5139",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
|
||||
"applicationUrl": "https://localhost:7023;http://localhost:5139",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
PersonaForge.Blazor/_Imports.razor
Normal file
11
PersonaForge.Blazor/_Imports.razor
Normal file
|
@ -0,0 +1,11 @@
|
|||
@using System.Net.Http
|
||||
@using System.Net.Http.Json
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@using Microsoft.AspNetCore.Components.WebAssembly.Http
|
||||
@using Microsoft.JSInterop
|
||||
@using PersonaForge.Blazor
|
||||
@using PersonaForge.Blazor.Layout
|
||||
@using PersonaForge
|
103
PersonaForge.Blazor/wwwroot/css/app.css
Normal file
103
PersonaForge.Blazor/wwwroot/css/app.css
Normal file
|
@ -0,0 +1,103 @@
|
|||
html, body {
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
h1:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
a, .btn-link {
|
||||
color: #0071c1;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color: #fff;
|
||||
background-color: #1b6ec2;
|
||||
border-color: #1861ac;
|
||||
}
|
||||
|
||||
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
|
||||
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-top: 1.1rem;
|
||||
}
|
||||
|
||||
.valid.modified:not([type=checkbox]) {
|
||||
outline: 1px solid #26b050;
|
||||
}
|
||||
|
||||
.invalid {
|
||||
outline: 1px solid red;
|
||||
}
|
||||
|
||||
.validation-message {
|
||||
color: red;
|
||||
}
|
||||
|
||||
#blazor-error-ui {
|
||||
background: lightyellow;
|
||||
bottom: 0;
|
||||
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
|
||||
display: none;
|
||||
left: 0;
|
||||
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
#blazor-error-ui .dismiss {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 0.75rem;
|
||||
top: 0.5rem;
|
||||
}
|
||||
|
||||
.blazor-error-boundary {
|
||||
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
|
||||
padding: 1rem 1rem 1rem 3.7rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.blazor-error-boundary::after {
|
||||
content: "An error has occurred."
|
||||
}
|
||||
|
||||
.loading-progress {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 8rem;
|
||||
height: 8rem;
|
||||
margin: 20vh auto 1rem auto;
|
||||
}
|
||||
|
||||
.loading-progress circle {
|
||||
fill: none;
|
||||
stroke: #e0e0e0;
|
||||
stroke-width: 0.6rem;
|
||||
transform-origin: 50% 50%;
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
.loading-progress circle:last-child {
|
||||
stroke: #1b6ec2;
|
||||
stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
|
||||
transition: stroke-dasharray 0.05s ease-in-out;
|
||||
}
|
||||
|
||||
.loading-progress-text {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
|
||||
}
|
||||
|
||||
.loading-progress-text:after {
|
||||
content: var(--blazor-load-percentage-text, "Loading");
|
||||
}
|
||||
|
||||
code {
|
||||
color: #c02d76;
|
||||
}
|
7
PersonaForge.Blazor/wwwroot/css/bootstrap/bootstrap.min.css
vendored
Normal file
7
PersonaForge.Blazor/wwwroot/css/bootstrap/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -14,8 +14,8 @@
|
|||
"TraitBiases": {
|
||||
"Outgoing": 0.9,
|
||||
"Playful": 0.8,
|
||||
"Active": 0.7,
|
||||
"Nice": 0.5,
|
||||
"Active": 0.5,
|
||||
"Nice": 0.7,
|
||||
"Neat": 0.3
|
||||
}
|
||||
},
|
122
PersonaForge.Blazor/wwwroot/data/zodiacs.json
Normal file
122
PersonaForge.Blazor/wwwroot/data/zodiacs.json
Normal file
|
@ -0,0 +1,122 @@
|
|||
[
|
||||
{
|
||||
"Name": "Aries",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 8.0,
|
||||
"Playful": 3.0,
|
||||
"Active": 7.0,
|
||||
"Nice": 3.0,
|
||||
"Neat": 4.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Taurus",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 4.0,
|
||||
"Playful": 4.0,
|
||||
"Active": 4.0,
|
||||
"Nice": 7.0,
|
||||
"Neat": 6.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Gemini",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 7.0,
|
||||
"Playful": 7.0,
|
||||
"Active": 4.0,
|
||||
"Nice": 3.0,
|
||||
"Neat": 4.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Cancer",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 4.0,
|
||||
"Playful": 3.0,
|
||||
"Active": 4.0,
|
||||
"Nice": 8.0,
|
||||
"Neat": 6.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Leo",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 8.0,
|
||||
"Playful": 7.0,
|
||||
"Active": 4.0,
|
||||
"Nice": 2.0,
|
||||
"Neat": 4.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Virgo",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 2.0,
|
||||
"Playful": 2.0,
|
||||
"Active": 4.0,
|
||||
"Nice": 8.0,
|
||||
"Neat": 9.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Libra",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 8.0,
|
||||
"Playful": 6.0,
|
||||
"Active": 4.0,
|
||||
"Nice": 5.0,
|
||||
"Neat": 2.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Scorpio",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 5.0,
|
||||
"Playful": 2.0,
|
||||
"Active": 8.0,
|
||||
"Nice": 4.0,
|
||||
"Neat": 6.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Sagittarius",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 7.0,
|
||||
"Playful": 7.0,
|
||||
"Active": 7.0,
|
||||
"Nice": 2.0,
|
||||
"Neat": 2.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Capricorn",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 3.0,
|
||||
"Playful": 2.0,
|
||||
"Active": 6.0,
|
||||
"Nice": 7.0,
|
||||
"Neat": 7.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Aquarius",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 6.0,
|
||||
"Playful": 7.0,
|
||||
"Active": 4.0,
|
||||
"Nice": 5.0,
|
||||
"Neat": 3.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Pisces",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 4.0,
|
||||
"Playful": 8.0,
|
||||
"Active": 4.0,
|
||||
"Nice": 5.0,
|
||||
"Neat": 4.0
|
||||
}
|
||||
}
|
||||
]
|
BIN
PersonaForge.Blazor/wwwroot/favicon.png
Normal file
BIN
PersonaForge.Blazor/wwwroot/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
PersonaForge.Blazor/wwwroot/icon-192.png
Normal file
BIN
PersonaForge.Blazor/wwwroot/icon-192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
32
PersonaForge.Blazor/wwwroot/index.html
Normal file
32
PersonaForge.Blazor/wwwroot/index.html
Normal file
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>PersonaForge.Blazor</title>
|
||||
<base href="/" />
|
||||
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="css/app.css" />
|
||||
<link rel="icon" type="image/png" href="favicon.png" />
|
||||
<link href="PersonaForge.Blazor.styles.css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<svg class="loading-progress">
|
||||
<circle r="40%" cx="50%" cy="50%" />
|
||||
<circle r="40%" cx="50%" cy="50%" />
|
||||
</svg>
|
||||
<div class="loading-progress-text"></div>
|
||||
</div>
|
||||
|
||||
<div id="blazor-error-ui">
|
||||
An unhandled error has occurred.
|
||||
<a href="" class="reload">Reload</a>
|
||||
<a class="dismiss">🗙</a>
|
||||
</div>
|
||||
<script src="_framework/blazor.webassembly.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
27
PersonaForge.Blazor/wwwroot/sample-data/weather.json
Normal file
27
PersonaForge.Blazor/wwwroot/sample-data/weather.json
Normal file
|
@ -0,0 +1,27 @@
|
|||
[
|
||||
{
|
||||
"date": "2022-01-06",
|
||||
"temperatureC": 1,
|
||||
"summary": "Freezing"
|
||||
},
|
||||
{
|
||||
"date": "2022-01-07",
|
||||
"temperatureC": 14,
|
||||
"summary": "Bracing"
|
||||
},
|
||||
{
|
||||
"date": "2022-01-08",
|
||||
"temperatureC": -13,
|
||||
"summary": "Freezing"
|
||||
},
|
||||
{
|
||||
"date": "2022-01-09",
|
||||
"temperatureC": -16,
|
||||
"summary": "Balmy"
|
||||
},
|
||||
{
|
||||
"date": "2022-01-10",
|
||||
"temperatureC": -2,
|
||||
"summary": "Chilly"
|
||||
}
|
||||
]
|
5
PersonaForge.Console/.config/dotnet-tools.json
Normal file
5
PersonaForge.Console/.config/dotnet-tools.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {}
|
||||
}
|
24
PersonaForge.Console/PersonaForge.Console.csproj
Normal file
24
PersonaForge.Console/PersonaForge.Console.csproj
Normal file
|
@ -0,0 +1,24 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Version>0.5.103</Version>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<PackAsTool>true</PackAsTool>
|
||||
<ToolCommandName>personaforge</ToolCommandName>
|
||||
<PackageId>PersonaForge</PackageId>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\PersonaForge\PersonaForge.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
68
PersonaForge.Console/Program.cs
Normal file
68
PersonaForge.Console/Program.cs
Normal file
|
@ -0,0 +1,68 @@
|
|||
// .NET 8 C# - Random Sims 2 Personality Allocator
|
||||
// Clear, minimal, portable, with basic validation.
|
||||
|
||||
using PersonaForge;
|
||||
|
||||
var rootCommand = new RootCommand("PersonaForge: Sims 2 Personality Generator");
|
||||
|
||||
var nameOption = new Option<string>(
|
||||
name: "--name",
|
||||
description: "Enter a name for the Sim"
|
||||
);
|
||||
|
||||
var archetypeOption = new Option<string>(
|
||||
name: "--archetype",
|
||||
description: "The archetype template to base traits on",
|
||||
getDefaultValue: () => "Random"
|
||||
);
|
||||
|
||||
var zodiacOption = new Option<bool>(
|
||||
name: "--zodiac",
|
||||
description: "Use zodiac signs instead of archetypes"
|
||||
)
|
||||
{ IsRequired = false };
|
||||
|
||||
var exportOption = new Option<bool>(
|
||||
name: "--export",
|
||||
description: "Export the generated profile to a file"
|
||||
)
|
||||
{ IsRequired = false };
|
||||
|
||||
rootCommand.AddOption(nameOption);
|
||||
rootCommand.AddOption(archetypeOption);
|
||||
rootCommand.AddOption(exportOption);
|
||||
|
||||
rootCommand.SetHandler(async (
|
||||
string name,
|
||||
string archetype,
|
||||
bool zodiac,
|
||||
bool export
|
||||
) =>
|
||||
{
|
||||
var archetypeDefs = Archetypes.LoadFromJson("archetypes.json");
|
||||
var archetypeDict = new Dictionary<string, Dictionary<string, double>>();
|
||||
|
||||
if (zodiac)
|
||||
archetypeDefs = Archetypes.LoadFromJson("zodiacs.json");
|
||||
|
||||
|
||||
|
||||
var traits = PersonalityGen.GenerateRandom(archetypeDict.GetValueOrDefault(archetype, new()));
|
||||
var profile = new PersonaProfile
|
||||
{
|
||||
Name = name,
|
||||
Qualities = traits,
|
||||
Archetype = archetype
|
||||
};
|
||||
|
||||
Console.WriteLine($"--- Generated Profile ---{Environment.NewLine}{PersonaProfile.ToJson(profile)}");
|
||||
|
||||
if (export)
|
||||
{
|
||||
var safeName = name.Replace(" ", "_").Replace("\"", "");
|
||||
await File.WriteAllTextAsync($"{safeName}.json", PersonaProfile.ToJson(profile));
|
||||
}
|
||||
|
||||
}, nameOption, archetypeOption, zodiacOption, exportOption);
|
||||
|
||||
return await rootCommand.InvokeAsync(args);
|
72
PersonaForge.Console/archetypes.json
Normal file
72
PersonaForge.Console/archetypes.json
Normal file
|
@ -0,0 +1,72 @@
|
|||
[
|
||||
{
|
||||
"Name": "Social Butterfly",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 0.9,
|
||||
"Playful": 0.8,
|
||||
"Active": 0.6,
|
||||
"Nice": 0.7,
|
||||
"Neat": 0.5
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Party Animal",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 0.9,
|
||||
"Playful": 0.8,
|
||||
"Active": 0.5,
|
||||
"Nice": 0.7,
|
||||
"Neat": 0.3
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Laidback",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 0.4,
|
||||
"Playful": 0.3,
|
||||
"Active": 0.4,
|
||||
"Nice": 0.8,
|
||||
"Neat": 0.4
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Grumpy",
|
||||
"TraitBiases": {
|
||||
"Nice": 0.2,
|
||||
"Playful": 0.4,
|
||||
"Outgoing": 0.6,
|
||||
"Neat": 0.7,
|
||||
"Active": 0.5
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Artistic",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 0.3,
|
||||
"Playful": 0.7,
|
||||
"Active": 0.5,
|
||||
"Nice": 0.9,
|
||||
"Neat": 0.6
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Ambitious",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 0.6,
|
||||
"Playful": 0.4,
|
||||
"Active": 0.8,
|
||||
"Nice": 0.5,
|
||||
"Neat": 0.7
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Adventurous",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 0.8,
|
||||
"Playful": 0.8,
|
||||
"Active": 0.9,
|
||||
"Nice": 0.6,
|
||||
"Neat": 0.4
|
||||
}
|
||||
}
|
||||
]
|
11
PersonaForge.Console/profiles/Max_Casey.json
Normal file
11
PersonaForge.Console/profiles/Max_Casey.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"Name": "Max Casey",
|
||||
"Archetype": "Party Animal",
|
||||
"Qualities": {
|
||||
"Outgoing": 7,
|
||||
"Nice": 6,
|
||||
"Playful": 6,
|
||||
"Neat": 3,
|
||||
"Active": 3
|
||||
}
|
||||
}
|
11
PersonaForge.Console/profiles/Zack_Casey.json
Normal file
11
PersonaForge.Console/profiles/Zack_Casey.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"Name": "Zack Casey",
|
||||
"Archetype": "Laidback",
|
||||
"Qualities": {
|
||||
"Outgoing": 5,
|
||||
"Nice": 8,
|
||||
"Playful": 4,
|
||||
"Neat": 4,
|
||||
"Active": 4
|
||||
}
|
||||
}
|
122
PersonaForge.Console/zodiacs.json
Normal file
122
PersonaForge.Console/zodiacs.json
Normal file
|
@ -0,0 +1,122 @@
|
|||
[
|
||||
{
|
||||
"Name": "Aries",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 8.0,
|
||||
"Playful": 3.0,
|
||||
"Active": 7.0,
|
||||
"Nice": 3.0,
|
||||
"Neat": 4.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Taurus",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 4.0,
|
||||
"Playful": 4.0,
|
||||
"Active": 4.0,
|
||||
"Nice": 7.0,
|
||||
"Neat": 6.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Gemini",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 7.0,
|
||||
"Playful": 7.0,
|
||||
"Active": 4.0,
|
||||
"Nice": 3.0,
|
||||
"Neat": 4.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Cancer",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 4.0,
|
||||
"Playful": 3.0,
|
||||
"Active": 4.0,
|
||||
"Nice": 8.0,
|
||||
"Neat": 6.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Leo",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 8.0,
|
||||
"Playful": 7.0,
|
||||
"Active": 4.0,
|
||||
"Nice": 2.0,
|
||||
"Neat": 4.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Virgo",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 2.0,
|
||||
"Playful": 2.0,
|
||||
"Active": 4.0,
|
||||
"Nice": 8.0,
|
||||
"Neat": 9.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Libra",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 8.0,
|
||||
"Playful": 6.0,
|
||||
"Active": 4.0,
|
||||
"Nice": 5.0,
|
||||
"Neat": 2.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Scorpio",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 5.0,
|
||||
"Playful": 2.0,
|
||||
"Active": 8.0,
|
||||
"Nice": 4.0,
|
||||
"Neat": 6.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Sagittarius",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 7.0,
|
||||
"Playful": 7.0,
|
||||
"Active": 7.0,
|
||||
"Nice": 2.0,
|
||||
"Neat": 2.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Capricorn",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 3.0,
|
||||
"Playful": 2.0,
|
||||
"Active": 6.0,
|
||||
"Nice": 7.0,
|
||||
"Neat": 7.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Aquarius",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 6.0,
|
||||
"Playful": 7.0,
|
||||
"Active": 4.0,
|
||||
"Nice": 5.0,
|
||||
"Neat": 3.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Pisces",
|
||||
"TraitBiases": {
|
||||
"Outgoing": 4.0,
|
||||
"Playful": 8.0,
|
||||
"Active": 4.0,
|
||||
"Nice": 5.0,
|
||||
"Neat": 4.0
|
||||
}
|
||||
}
|
||||
]
|
34
PersonaForge.sln
Normal file
34
PersonaForge.sln
Normal file
|
@ -0,0 +1,34 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PersonaForge.Console", "PersonaForge.Console\PersonaForge.Console.csproj", "{129AB949-1C7E-4E52-82E0-9339F43918AA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PersonaForge", "PersonaForge\PersonaForge.csproj", "{316741E2-8BE3-4FBF-A10D-F8FF2AD6979E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PersonaForge.Blazor", "PersonaForge.Blazor\PersonaForge.Blazor.csproj", "{381CCDD1-BB1A-45F0-8501-77769AB4578F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{129AB949-1C7E-4E52-82E0-9339F43918AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{129AB949-1C7E-4E52-82E0-9339F43918AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{129AB949-1C7E-4E52-82E0-9339F43918AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{129AB949-1C7E-4E52-82E0-9339F43918AA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{316741E2-8BE3-4FBF-A10D-F8FF2AD6979E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{316741E2-8BE3-4FBF-A10D-F8FF2AD6979E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{316741E2-8BE3-4FBF-A10D-F8FF2AD6979E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{316741E2-8BE3-4FBF-A10D-F8FF2AD6979E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{381CCDD1-BB1A-45F0-8501-77769AB4578F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{381CCDD1-BB1A-45F0-8501-77769AB4578F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{381CCDD1-BB1A-45F0-8501-77769AB4578F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{381CCDD1-BB1A-45F0-8501-77769AB4578F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
91
PersonaForge/Archetypes.cs
Normal file
91
PersonaForge/Archetypes.cs
Normal file
|
@ -0,0 +1,91 @@
|
|||
namespace PersonaForge;
|
||||
|
||||
public class Archetypes
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public Dictionary<string, double> TraitBiases { get; set; } = new();
|
||||
|
||||
public static List<Archetypes> LoadFromJson(string json)
|
||||
{
|
||||
var opt = new JsonSerializerOptions()
|
||||
{
|
||||
PropertyNameCaseInsensitive = false
|
||||
};
|
||||
|
||||
var definitions = JsonSerializer.Deserialize<List<Archetypes>>(json, opt);
|
||||
|
||||
if (definitions is null)
|
||||
throw new InvalidOperationException("Failed to deserialize Archetype JSON.");
|
||||
|
||||
return definitions;
|
||||
}
|
||||
|
||||
public static List<Archetypes> DefaultArchetypes() => new()
|
||||
{
|
||||
new Archetypes
|
||||
{
|
||||
Name = "Grumpy",
|
||||
TraitBiases = new Dictionary<string, double>
|
||||
{
|
||||
{ "Nice", 0.2 },
|
||||
{ "Playful", 0.4 },
|
||||
{ "Outgoing", 0.6 },
|
||||
{ "Neat", 0.7 },
|
||||
{ "Active", 0.5 }
|
||||
}
|
||||
},
|
||||
new Archetypes
|
||||
{
|
||||
Name = "Party Animal",
|
||||
TraitBiases = new Dictionary<string, double>
|
||||
{
|
||||
{ "Outgoing", 0.9 },
|
||||
{ "Playful", 0.8 },
|
||||
{ "Active", 0.7 },
|
||||
{ "Nice", 0.5 },
|
||||
{ "Neat", 0.3 }
|
||||
}
|
||||
},
|
||||
new Archetypes
|
||||
{
|
||||
Name = "Lazy",
|
||||
TraitBiases = new Dictionary<string, double>
|
||||
{
|
||||
{ "Nice", 0.8 },
|
||||
{ "Playful", 0.6 },
|
||||
{ "Outgoing", 0.4 },
|
||||
{ "Neat", 0.2 },
|
||||
{ "Active", 0.1 }
|
||||
}
|
||||
},
|
||||
new Archetypes
|
||||
{
|
||||
Name = "Shy",
|
||||
TraitBiases = new Dictionary<string, double>
|
||||
{
|
||||
{ "Nice", 0.9 },
|
||||
{ "Playful", 0.7 },
|
||||
{ "Outgoing", 0.3 },
|
||||
{ "Neat", 0.5 },
|
||||
{ "Active", 0.2 }
|
||||
}
|
||||
},
|
||||
new Archetypes
|
||||
{
|
||||
Name = "Energetic",
|
||||
TraitBiases = new Dictionary<string, double>
|
||||
{
|
||||
{ "Nice", 0.7 },
|
||||
{ "Playful", 0.6 },
|
||||
{ "Outgoing", 0.5 },
|
||||
{ "Neat", 0.4 },
|
||||
{ "Active", 0.3 }
|
||||
}
|
||||
},
|
||||
new Archetypes
|
||||
{
|
||||
Name = "Random",
|
||||
TraitBiases = new()
|
||||
}
|
||||
};
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Version>0.3.101</Version>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Version>0.5.103</Version>
|
||||
<VersionSuffix>lts</VersionSuffix>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
|
@ -6,12 +6,24 @@ public static class PersonalityGen
|
|||
const int TotalBudget = 25;
|
||||
static readonly Random rng = new();
|
||||
|
||||
public static PersonalityTraits GenerateRandom()
|
||||
public static PersonalityTraits GenerateRandom(Dictionary<string, double>? bias = null)
|
||||
{
|
||||
var profile = PersonalityTraits.Create();
|
||||
var traits = new List<string> { "Outgoing", "Nice", "Playful", "Neat", "Active" };
|
||||
var remaining = TotalBudget;
|
||||
|
||||
if (bias != null)
|
||||
{
|
||||
foreach (var kvp in bias)
|
||||
{
|
||||
var trait = kvp.Key;
|
||||
var points = Convert.ToInt32(kvp.Value);
|
||||
var safePoints = Math.Min(points, MaxPoints);
|
||||
SetTraitPoints(profile, trait, safePoints);
|
||||
remaining -= points;
|
||||
}
|
||||
}
|
||||
|
||||
while (remaining > 0)
|
||||
{
|
||||
var trait = traits[rng.Next(traits.Count)];
|
|
@ -2,11 +2,11 @@ namespace PersonaForge;
|
|||
|
||||
public class PersonalityTraits
|
||||
{
|
||||
public int Outgoing { get; set; }
|
||||
public int Nice { get; set; }
|
||||
public int Playful { get; set; }
|
||||
public int Neat { get; set; }
|
||||
public int Outgoing { get; set; }
|
||||
public int Active { get; set; }
|
||||
public int Playful { get; set; }
|
||||
public int Nice { get; set; }
|
||||
|
||||
public static PersonalityTraits Create() => new();
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
namespace PersonaForge;
|
||||
|
||||
public class PersonalityArchetype
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public Dictionary<string, double> TraitBiases { get; set; } = new();
|
||||
|
||||
// TODO: Load default archetypes from a file or database
|
||||
public static List<PersonalityArchetype> DefaultArchetypes() => new()
|
||||
{
|
||||
new PersonalityArchetype
|
||||
{
|
||||
Name = "Grumpy",
|
||||
TraitBiases = new Dictionary<string, double>
|
||||
{
|
||||
{ "Nice", 0.2 },
|
||||
{ "Playful", 0.4 },
|
||||
{ "Outgoing", 0.6 },
|
||||
{ "Neat", 0.7 },
|
||||
{ "Active", 0.5 }
|
||||
}
|
||||
},
|
||||
new PersonalityArchetype
|
||||
{
|
||||
Name = "Party Animal",
|
||||
TraitBiases = new Dictionary<string, double>
|
||||
{
|
||||
{ "Outgoing", 0.9 },
|
||||
{ "Playful", 0.8 },
|
||||
{ "Active", 0.7 },
|
||||
{ "Nice", 0.5 },
|
||||
{ "Neat", 0.3 }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
32
Program.cs
32
Program.cs
|
@ -1,32 +0,0 @@
|
|||
// .NET 8 C# - Random Sims 2 Personality Allocator
|
||||
// Clear, minimal, portable, with basic validation.
|
||||
|
||||
using PersonaForge;
|
||||
|
||||
Console.WriteLine("=== Welcome to The Sims 2 Personality Generator ===");
|
||||
|
||||
Console.Write("Enter Sim's name: ");
|
||||
string name = Console.ReadLine() ?? "Unndanmed Sim";
|
||||
|
||||
var qualities = PersonalityGen.GenerateRandom();
|
||||
var profile = new PersonaProfile
|
||||
{
|
||||
Name = name,
|
||||
Qualities = qualities,
|
||||
Archetype = "Random"
|
||||
};
|
||||
|
||||
Console.WriteLine($"{name}'s Profile{Environment.NewLine}{PersonaProfile.ToJson(profile)}");
|
||||
|
||||
Console.Write("Save profile? (y/n): ");
|
||||
var saveInput = Console.ReadLine()?.Trim().ToLowerInvariant();
|
||||
|
||||
if (saveInput == "y")
|
||||
{
|
||||
var safeName = name.Replace(" ", "_").Replace("\"", "");
|
||||
File.WriteAllText($"{safeName}.json", PersonaProfile.ToJson(profile));
|
||||
Console.WriteLine($"Profile saved as {name}.json");
|
||||
}
|
||||
|
||||
Console.WriteLine($"Done. Forge on! 🔥{Environment.NewLine}Press any key to exit...");
|
||||
Console.ReadKey();
|
36
README.md
36
README.md
|
@ -10,18 +10,24 @@ It helps if you want to:
|
|||
|
||||
## 💡 Why This Exists
|
||||
|
||||
With Sims 3 and later, creating personalities is as simple as selecting a trait. Sims 2 doesn’t have traits in the same way later installments do. You had to figure out what kind of Sim you wanted based on certain qualities and points you had to spend. Even if you knew what you wanted, you didn’t know how to spend the rest. This was created to solve that.
|
||||
Because The Sims 2 doesn’t have traits in the same way later installments do, you had to figure out what kind of Sim you wanted based on personality stats with a strict 25 point budget. Even if you knew what you wanted, you didn’t always know how to spend the rest. PersonaForge aimed to solve this problem.
|
||||
|
||||
## 🛣️ Project Roadmap
|
||||
|
||||
| Phase | Goal | Status |
|
||||
| ----- | ------------------------------------------- | ------ |
|
||||
| v0.1 | Core random point generator (working) | ✅ |
|
||||
| -------- | ------------------------------------------- | ------ |
|
||||
| v0.1 | Core random point generator | ✅ |
|
||||
| v0.2 | PersonalityProfile class | ✅ |
|
||||
| v0.3 | Interactive JSON export | ✅ |
|
||||
| v0.4 | Archetypes with weighted biases | 🔜 |
|
||||
| v0.5 | Profile import/load from JSON | 🔜 |
|
||||
| v0.4 | Archetypes with weighted biases | ✅ |
|
||||
| v0.5 LTS | Command line tool | ✅ |
|
||||
| v1.0 | Stable "Release" version with documentation | 🔜 |
|
||||
| v1.x | Profile import/load from JSON | 🔜 |
|
||||
|
||||
## 📌 Stretch Goals
|
||||
|
||||
- [x] Import The Sims' Zodiac signs
|
||||
- [x] Cross-platform dotnet tool. (e.g. `dotnet tool install`)
|
||||
|
||||
## 🧩 Tech Stack
|
||||
|
||||
|
@ -38,17 +44,22 @@ With Sims 3 and later, creating personalities is as simple as selecting a trait.
|
|||
- Futureproof for new archetypes, quirks, or expansions
|
||||
- Portable and clean
|
||||
|
||||
## 📦 Example JSON Output
|
||||
## 📦 Example
|
||||
|
||||
```shell
|
||||
personaforge --name "Max Casey" --archetype "Party Animal" (--export)
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"Name": "Max Casey",
|
||||
"Archetype": "Party Animal",
|
||||
"Qualities": {
|
||||
"Outgoing": 6,
|
||||
"Nice": 4,
|
||||
"Outgoing": 7,
|
||||
"Nice": 6,
|
||||
"Playful": 6,
|
||||
"Neat": 5,
|
||||
"Active": 4
|
||||
"Neat": 3,
|
||||
"Active": 3
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -56,13 +67,8 @@ With Sims 3 and later, creating personalities is as simple as selecting a trait.
|
|||
## 🚫 Not Planned
|
||||
|
||||
- No Sim 3-style traits.
|
||||
- No UI. (Maybe a fork)
|
||||
- No CAS-style tool.
|
||||
|
||||
## 📌 Stretch Goals
|
||||
|
||||
- Cross-platform dotnet tool. (e.g. `dotnet tool install`)
|
||||
|
||||
## 🗓️ Update Cycle
|
||||
|
||||
| Type | Frequency | Notes |
|
||||
|
|
Loading…
Add table
Reference in a new issue