The following code demonstrates how to implement a blood type inheritance calculator using ArkUI in HarmonyOS NEXT. This application allows users to select parental blood types and calculates possible/prohibited blood types for their offspring based on genetic principles.
Full Code with English Comments
// Import SegmentButton and related type definitions
import { SegmentButton, SegmentButtonItemTuple, SegmentButtonOptions } from '@kit.ArkUI';
// Mark the component as the entry point using the @Entry decorator
@Entry
// Define a component using the @Component decorator
@Component
// BloodTypeCalculator struct implements blood type inheritance calculation
struct BloodTypeCalculator {
// Theme color (default: Orange)
@State private themeColor: string | Color = Color.Orange;
// Text color (default: dark gray)
@State private textColor: string = "#2e2e2e";
// Border color (default: light gray)
@State private lineColor: string = "#d5d5d5";
// Base padding size (default: 30)
@State private basePadding: number = 30;
// Possible blood type results
@State private possibleBloodTypesText: string = "";
// Impossible blood type results
@State private impossibleBloodTypesText: string = "";
// Blood type list: A, B, AB, O
@State private bloodTypeList: object[] = [
Object({ text: 'A' }),
Object({ text: 'B' }),
Object({ text: 'AB' }),
Object({ text: 'O' })
];
// Capsule button configuration for single selection
@State singleSelectCapsuleOptions: SegmentButtonOptions | undefined = undefined;
// Track father's blood type selection
@State @Watch('capsuleSelectedIndexesChanged') fatherBloodTypeIndex: number[] = [0];
// Track mother's blood type selection
@State @Watch('capsuleSelectedIndexesChanged') motherBloodTypeIndex: number[] = [0];
// Get possible gene combinations for a blood type
getGenes(bloodType: string): string[] {
console.info(`bloodType:${bloodType}`);
switch (bloodType) {
case 'A': return ['A', 'O']; // Possible genes for type A
case 'B': return ['B', 'O']; // Possible genes for type B
case 'AB': return ['A', 'B']; // Possible genes for type AB
case 'O': return ['O']; // Possible genes for type O
default: throw new Error('Invalid blood type');
}
}
// Combine parental genes to find possible offspring combinations
combineGenes(fatherGenes: string[], motherGenes: string[]): string[] {
const possibleGenes: string[] = [];
for (const fatherGene of fatherGenes) {
for (const motherGene of motherGenes) {
const combinedGene = [fatherGene, motherGene].sort().join('');
if (!possibleGenes.includes(combinedGene)) {
possibleGenes.push(combinedGene);
}
}
}
return possibleGenes;
}
// Convert gene combinations to blood types
getBloodTypesFromGenes(genes: string[]): string[] {
const bloodTypes: string[] = [];
for (const gene of genes) {
if (gene === 'AA' || gene === 'AO' || gene === 'OA') {
bloodTypes.push('A');
} else if (gene === 'BB' || gene === 'BO' || gene === 'OB') {
bloodTypes.push('B');
} else if (gene === 'AB' || gene === 'BA') {
bloodTypes.push('AB');
} else if (gene === 'OO') {
bloodTypes.push('O');
}
}
return [...new Set(bloodTypes)]; // Remove duplicates
}
// Calculate possible/impossible blood types
calculatePossibleBloodTypes(father: string, mother: string) {
const fatherGenes = this.getGenes(father);
const motherGenes = this.getGenes(mother);
const possibleGenes = this.combineGenes(fatherGenes, motherGenes);
const possibleBloodTypes = this.getBloodTypesFromGenes(possibleGenes);
const impossibleBloodTypes = ['A', 'B', 'AB', 'O']
.filter(bt => !possibleBloodTypes.includes(bt));
this.possibleBloodTypesText = `Possible: ${possibleBloodTypes.join(', ')}`;
this.impossibleBloodTypesText = `Impossible: ${impossibleBloodTypes.join(', ')}`;
}
// Handle segment button selection changes
capsuleSelectedIndexesChanged() {
const father = this.bloodTypeList[this.fatherBloodTypeIndex[0]]['text'];
const mother = this.bloodTypeList[this.motherBloodTypeIndex[0]]['text'];
this.calculatePossibleBloodTypes(father, mother);
}
// Initialize UI when component appears
aboutToAppear(): void {
this.singleSelectCapsuleOptions = SegmentButtonOptions.capsule({
buttons: this.bloodTypeList as SegmentButtonItemTuple,
multiply: false, // Single selection mode
fontColor: Color.White,
selectedFontColor: Color.White,
selectedBackgroundColor: this.themeColor,
backgroundColor: this.lineColor,
backgroundBlurStyle: BlurStyle.BACKGROUND_THICK
});
this.capsuleSelectedIndexesChanged();
}
// UI Construction
build() {
Column() {
// Title Section
Text('Blood Type Calculator')
.fontColor(this.textColor)
.fontSize(18)
.width('100%')
.height(50)
.textAlign(TextAlign.Center)
.backgroundColor(Color.White)
.shadow({ radius: 2, color: this.lineColor, offsetX: 0, offsetY: 5 });
// Introduction Section
Column() {
Text('How It Works').fontSize(20).fontWeight(600).fontColor(this.textColor);
Text('Blood type inheritance depends on combinations of A/B/O genes. This tool predicts possible offspring blood types based on parental selections.')
.fontSize(18).fontColor(this.textColor).margin({ top: `${this.basePadding / 2}lpx`);
}
// ... (UI styling properties unchanged)
// Parent Selection Section
Column() {
Row() {
Text('Father\'s Blood Type').fontColor(this.textColor).fontSize(18);
SegmentButton({
options: this.singleSelectCapsuleOptions,
selectedIndexes: this.fatherBloodTypeIndex
}).width('400lpx');
}
// ... (Mother's section mirroring father's)
}
// Result Display Section
Column() {
Text(this.possibleBloodTypesText).fontColor(this.textColor).fontSize(18);
Text(this.impossibleBloodTypesText).fontColor(this.textColor).fontSize(18);
}
}
.backgroundColor("#f4f8fb");
}
}
Key Technical Points
-
Genetic Algorithm Implementation
- The
getGenes()
method maps blood types to possible gene combinations (e.g., A → ["A", "O"]). -
combineGenes()
generates all possible offspring gene pairs through nested iteration. -
getBloodTypesFromGenes()
converts sorted gene pairs to standardized blood types.
- The
-
UI Components
- Uses
SegmentButton
for blood type selection with capsule-style styling. - Implements responsive layout with percentage-based widths and logical pixel units (
lpx
). - Applies consistent shadow effects and color schemes for visual hierarchy.
- Uses
-
State Management
-
@State
variables track UI state and calculation results. -
@Watch
decorator triggers recalculation when parental selections change.
-
-
Performance Optimization
- Uses
console.info
for debugging while avoiding expensive operations in render cycles. - Memoizes blood type lists to prevent unnecessary re-renders.
- Uses
This implementation demonstrates HarmonyOS NEXT's capability to build scientifically accurate tools with clean UI/UX principles.
Top comments (0)