🎥 EstudioVirtual — Rascunho de uma simulação de profissionais
São 00:54 enquanto escrevo isso no Obsidian. Tô tomando um Monster (Pacific Punch). Gostei bastante até.
A ideia original era começar a modelar o CRUD de uma produção, mas acabei desanimando. Aí veio o estalo: e se eu começasse pelos profissionais que compõem uma produção? Ator, diretor, dublê... Afinal, são eles que dão vida ao projeto, junto com o produtor.
Então, rabisquei um primeiro esboço de um sistema de trabalhadores inspirando-me no TMDB (The Movie Database), com o objetivo de simular pessoas com diferentes características, funções, habilidades e personalidades.
Deixei tudo comentado para ajudar no entendimento!
Classe Crew
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Crew {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
// Sexo/Gênero (Masculino, Feminino e Não Binário)
@Enumerated(EnumType.STRING)
private GenderEnum gender;
// Papel do profissional (ator, diretor, roteirista...)
@Enumerated(EnumType.STRING)
private CrewRoleEnum role;
// Gênero cinematográfico de especialização (ação, drama, etc)
@Enumerated(EnumType.STRING)
private GenreEnum specialtie;
// Traços de personalidade do indivíduo (ainda a ser detalhada)
@ElementCollection
@Enumerated(EnumType.STRING)
private Set<PersonalityTraitEnum> personalityTraits = new HashSet<>();
// Atributos de desempenho e características pessoais (ainda a ser detalhada)
private Integer popularity;
private Integer artisticCreativity;
private Integer experience;
private Integer productivity;
private Integer stress;
// Flags de status
private Boolean isAdult;
private Boolean isDead = false;
private Boolean isOnVacation;
private Boolean isAvailable;
// Datas importantes
private LocalDate birthDate;
private LocalDate deathDate;
private LocalDate vacationStartDate;
private LocalDate vacationEndDate;
// Salário base esperado
private BigDecimal baseSalary;
// Relação com contratos (ainda a ser detalhada)
@OneToMany(mappedBy = "crew", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Contract> contracts = new HashSet<>();
}
Enum de Funções
Listei os principais papéis da indústria criativa. A ideia é que cada um tenha comportamento, salário e faixa etária própria
public enum CrewRoleEnum {
ACTOR,
DIRECTOR,
SCREENWRITER,
CINEMATOGRAPHER,
EDITOR,
COMPOSER,
ART_DIRECTOR,
COSTUME_DESIGNER,
SOUND_DESIGNER,
VISUAL_EFFECTS_SUPERVISOR,
WRITER,
VFX_ARTIST,
MAKEUP_ARTIST,
STUNT_PERFORMER
}
Enum de Personalidade
Ainda em construção, mas já temos alguns traços para influenciar decisões e interações futuras
public enum PersonalityTraitEnum {
WORKAHOLIC,
PRODIGIO,
GASTADOR,
CAPITALISTA
}
Geração Automática de Profissionais
Criei um serviço para gerar 50 profissionais aleatórios. A ideia aqui é testar como a combinação de idade, papel, personalidade e atributos impacta nos salários, além de servir para fazer testes de população (vou comentar mais pra frente)
public void generateRandomCrews() {
List<Crew> crews = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 50; i++) {
// Geração de atributos aleatórios
Set<PersonalityTraitEnum> traits = generateRandomPersonalities();
CrewRoleEnum role = CrewRoleEnum.values()[random.nextInt(CrewRoleEnum.values().length)];
LocalDate birthDate = generateRandomBirthDate(role);
GenderEnum gender = GenderEnum.values()[random.nextInt(GenderEnum.values().length)];
GenreEnum specialty = GenreEnum.values()[random.nextInt(GenreEnum.values().length)];
int age = Period.between(birthDate, LocalDate.now()).getYears();
int experience = experienceService.calculateExperience(role, specialty, age);
int popularity = random.nextInt(101);
int artisticCreativity = random.nextInt(101);
int productivity = random.nextInt(101);
BigDecimal baseSalary = salaryService.calculateSalary(
role, specialty, age, experience, popularity, artisticCreativity, productivity
);
// Construção do objeto Crew
Crew crew = Crew.builder()
.firstName(crewGenerateNameService.generateFirstName(random, gender.name()))
.lastName(crewGenerateNameService.generateLastName(random))
.gender(gender)
.role(role)
.specialtie(specialty)
.personalityTraits(traits)
.popularity(popularity)
.artisticCreativity(artisticCreativity)
.experience(experience)
.productivity(productivity)
.stress(random.nextInt(101))
.isAdult(true)
.isDead(false)
.isOnVacation(random.nextDouble() < 0.1)
.isAvailable(random.nextDouble() < 0.9)
.birthDate(birthDate)
.baseSalary(baseSalary)
.build();
// Se a pessoa estiver de férias, configura datas e disponibilidade
if (Boolean.TRUE.equals(crew.getIsOnVacation())) {
LocalDate today = LocalDate.now();
crew.setVacationStartDate(today.minusDays(random.nextInt(7)));
crew.setVacationEndDate(today.plusDays(random.nextInt(14) + 1));
crew.setIsAvailable(false);
}
crews.add(crew);
}
// Salva todos os funcionários no banco
crewRepository.saveAll(crews);
}
Idade + papel + gênero = XP
A experiência é baseada na idade, considerando um início típico de carreira por papel e com multiplicadores que variam pelo gênero cinematográfico (bem legal, mas longe de ser realista)
public int calculateExperience(CrewRoleEnum role, GenreEnum specialty, Integer age) {
int baseMaxExperience = age - getMinimumEducationAge(role);
if (baseMaxExperience <= 0) return 0;
// Variação aleatória de experiência, multiplicadores de cargo e gênero
double baseExperienceRatio = 0.5 + (Math.random() * 0.5);
double roleMultiplier = getRoleExperienceMultiplier(role);
double specialtyMultiplier = getSpecialtyExperienceMultiplier(specialty);
double finalExperience = baseMaxExperience * baseExperienceRatio * roleMultiplier * specialtyMultiplier;
return (int) Math.round(finalExperience);
}
Salário Baseado em "mérito", demanda e experiência (O mais complicado de gerar realismo)
Apenser de ser complicado, o cálculo do salário é meu trecho favorito — mistura lógica de mercado com métricas individuais é meio que brincar de Deus. Por favor, tente fazer um sistema assim!
public BigDecimal calculateSalary(...) {
// Faixa de salário base por papel
Map<CrewRoleEnum, double[]> roleSalaryRanges = getRoleSalaryRanges();
double[] salaryRange = roleSalaryRanges.getOrDefault(role, new double[]{4000.0, 60000.0});
// Calcula a experiência com base na idade
double experienceFactor = getExperienceFactor(age, experience, role);
// Base + mercado + performance
double baseSalary = salaryRange[0] + ((salaryRange[1] - salaryRange[0]) * experienceFactor);
double marketMultiplier = getMarketMultiplier(role, specialty);
double careerStageMultiplier = getCareerStageMultiplier(age, experience);
double performanceMultiplier = calculatePerformanceMultiplier(popularity, artisticCreativity, productivity, role);
double finalSalary = baseSalary * marketMultiplier * careerStageMultiplier * performanceMultiplier;
// Variação de ±8%
double marketVariation = 0.92 + (Math.random() * 0.16);
finalSalary *= marketVariation;
return BigDecimal.valueOf(finalSalary).setScale(2, RoundingMode.HALF_UP);
}
Considerações Finais
Ainda tenho muito para desenvolver:
- Implementar o sistema de contratos.
- Lógica de Oferta/Demanda que afete salários dinamicamente.
- Lógicas mais elaboras para representar os atributos de uma pessoa.
- Personalidade influenciando atributos.
Nota: O salário base aqui representa o valor "mínimo" que um profissional aceitaria, mas esse valor pode ser negociado dependendo do tipo de contrato, duração e benefícios.
Queria saber a opinião de vocês:
- O que vocês acham da modelagem?
- Ideias de atributos ou mecânicas interessantes?
- Alguma referência legal de simulação que eu deveria estudar?
Obrigado se leu até aqui! 😄