Change shear calculator add crack export to excel

This commit is contained in:
Evgeny Redikultsev
2025-06-21 21:34:20 +05:00
parent 4fbb3f3658
commit 1ebe1bbcd1
47 changed files with 980 additions and 378 deletions

View File

@@ -13,6 +13,7 @@ namespace DataAccess.DTOs
private IUpdateStrategy<IBeamShearSection> updateStrategy; private IUpdateStrategy<IBeamShearSection> updateStrategy;
private IConvertStrategy<IShape, IShape> shapeConvertStrategy; private IConvertStrategy<IShape, IShape> shapeConvertStrategy;
private IConvertStrategy<ConcreteLibMaterial, ConcreteLibMaterialDTO> concreteConvertStrategy; private IConvertStrategy<ConcreteLibMaterial, ConcreteLibMaterialDTO> concreteConvertStrategy;
private IConvertStrategy<ReinforcementLibMaterial, ReinforcementLibMaterialDTO> reinforcementConvertStrategy;
private IUpdateStrategy<IHelperMaterial> safetyFactorUpdateStrategy; private IUpdateStrategy<IHelperMaterial> safetyFactorUpdateStrategy;
@@ -26,12 +27,17 @@ namespace DataAccess.DTOs
NewItem = new(source.Id); NewItem = new(source.Id);
updateStrategy.Update(NewItem, source); updateStrategy.Update(NewItem, source);
NewItem.Shape = shapeConvertStrategy.Convert(source.Shape); NewItem.Shape = shapeConvertStrategy.Convert(source.Shape);
if (source.Material is not ConcreteLibMaterialDTO concreteDTO) if (source.ConcreteMaterial is not ConcreteLibMaterialDTO concreteDTO)
{ {
throw new StructureHelperException(ErrorStrings.ObjectTypeIsUnknownObj(source.Material)); throw new StructureHelperException(ErrorStrings.ObjectTypeIsUnknownObj(source.ConcreteMaterial));
} }
NewItem.Material = concreteConvertStrategy.Convert(concreteDTO); NewItem.ConcreteMaterial = concreteConvertStrategy.Convert(concreteDTO);
safetyFactorUpdateStrategy.Update(NewItem.Material, concreteDTO); safetyFactorUpdateStrategy.Update(NewItem.ConcreteMaterial, concreteDTO);
if (source.ReinforcementMaterial is not ReinforcementLibMaterialDTO reinforcement)
{
throw new StructureHelperException(ErrorStrings.ObjectTypeIsUnknownObj(source.ReinforcementMaterial));
}
NewItem.ReinforcementMaterial = reinforcementConvertStrategy.Convert(reinforcement);
return NewItem; return NewItem;
} }
@@ -45,6 +51,11 @@ namespace DataAccess.DTOs
ReferenceDictionary = ReferenceDictionary, ReferenceDictionary = ReferenceDictionary,
TraceLogger = TraceLogger TraceLogger = TraceLogger
}; };
reinforcementConvertStrategy = new ReinforcementLibMaterialFromDTOConvertStrategy()
{
ReferenceDictionary = ReferenceDictionary,
TraceLogger = TraceLogger
};
safetyFactorUpdateStrategy = new HelperMaterialDTOSafetyFactorUpdateStrategy(new MaterialSafetyFactorsFromDTOLogic()); safetyFactorUpdateStrategy = new HelperMaterialDTOSafetyFactorUpdateStrategy(new MaterialSafetyFactorsFromDTOLogic());
} }
} }

View File

@@ -12,6 +12,7 @@ namespace DataAccess.DTOs
private IUpdateStrategy<IBeamShearSection> updateStrategy; private IUpdateStrategy<IBeamShearSection> updateStrategy;
private IConvertStrategy<IShape, IShape> shapeConvertStrategy; private IConvertStrategy<IShape, IShape> shapeConvertStrategy;
private IConvertStrategy<ConcreteLibMaterialDTO, IConcreteLibMaterial> concreteConvertStrategy; private IConvertStrategy<ConcreteLibMaterialDTO, IConcreteLibMaterial> concreteConvertStrategy;
private ReinforcementLibMaterialToDTOConvertStrategy reinforcementConvertStrategy;
private IUpdateStrategy<IHelperMaterial> safetyFactorUpdateStrategy; private IUpdateStrategy<IHelperMaterial> safetyFactorUpdateStrategy;
public BeamShearSectionToDTOConvertStrategy(Dictionary<(Guid id, Type type), ISaveable> referenceDictionary, IShiftTraceLogger traceLogger) public BeamShearSectionToDTOConvertStrategy(Dictionary<(Guid id, Type type), ISaveable> referenceDictionary, IShiftTraceLogger traceLogger)
@@ -40,8 +41,10 @@ namespace DataAccess.DTOs
NewItem = new(source.Id); NewItem = new(source.Id);
updateStrategy.Update(NewItem, source); updateStrategy.Update(NewItem, source);
NewItem.Shape = shapeConvertStrategy.Convert(source.Shape); NewItem.Shape = shapeConvertStrategy.Convert(source.Shape);
NewItem.Material = concreteConvertStrategy.Convert(source.Material); NewItem.ConcreteMaterial = concreteConvertStrategy.Convert(source.ConcreteMaterial);
safetyFactorUpdateStrategy.Update(NewItem.Material, source.Material); safetyFactorUpdateStrategy.Update(NewItem.ConcreteMaterial, source.ConcreteMaterial);
NewItem.ReinforcementMaterial = reinforcementConvertStrategy.Convert(source.ReinforcementMaterial);
safetyFactorUpdateStrategy.Update(NewItem.ReinforcementMaterial, source.ReinforcementMaterial);
TraceLogger?.AddMessage($"Beam shear section converting Id = {NewItem.Id} has been finished succesfully", TraceLogStatuses.Debug); TraceLogger?.AddMessage($"Beam shear section converting Id = {NewItem.Id} has been finished succesfully", TraceLogStatuses.Debug);
} }
@@ -53,6 +56,11 @@ namespace DataAccess.DTOs
concreteConvertStrategy = new ConcreteLibMaterialToDTOConvertStrategy() concreteConvertStrategy = new ConcreteLibMaterialToDTOConvertStrategy()
{ ReferenceDictionary = ReferenceDictionary, { ReferenceDictionary = ReferenceDictionary,
TraceLogger = TraceLogger}; TraceLogger = TraceLogger};
reinforcementConvertStrategy = new ReinforcementLibMaterialToDTOConvertStrategy()
{
ReferenceDictionary = ReferenceDictionary,
TraceLogger = TraceLogger
};
safetyFactorUpdateStrategy = new HelperMaterialDTOSafetyFactorUpdateStrategy(new MaterialSafetyFactorToDTOLogic()); safetyFactorUpdateStrategy = new HelperMaterialDTOSafetyFactorUpdateStrategy(new MaterialSafetyFactorToDTOLogic());
} }
} }

View File

@@ -16,10 +16,15 @@ namespace DataAccess.DTOs
public string? Name { get; set; } public string? Name { get; set; }
[JsonProperty("Shape")] [JsonProperty("Shape")]
public IShape Shape { get; set; } = new RectangleShapeDTO(Guid.Empty); public IShape Shape { get; set; } = new RectangleShapeDTO(Guid.Empty);
[JsonProperty("Material")] [JsonProperty("ConcreteMaterial")]
public IConcreteLibMaterial Material { get; set; } public IConcreteLibMaterial ConcreteMaterial { get; set; }
[JsonProperty("CenterCover")] [JsonProperty("CenterCover")]
public double CenterCover { get; set; } public double CenterCover { get; set; }
[JsonProperty("ReinforcementArea")]
public double ReinforcementArea { get; set; }
[JsonProperty("ReinforcementMaterial")]
public IReinforcementLibMaterial ReinforcementMaterial { get; set; }
public BeamShearSectionDTO(Guid id) public BeamShearSectionDTO(Guid id)
{ {
Id = id; Id = id;

View File

@@ -158,6 +158,7 @@
<DataTemplate x:Key="Back"> <DataTemplate x:Key="Back">
<Path Margin="4" Data="M -1 18 l 2 -9 l 1 3 a 15 15 90 0 1 22 -3 l -2 4 a 13 13 90 0 0 -18 2 l 3 3 z" Fill="White" Stroke="Black"/> <Path Margin="4" Data="M -1 18 l 2 -9 l 1 3 a 15 15 90 0 1 22 -3 l -2 4 a 13 13 90 0 0 -18 2 l 3 3 z" Fill="White" Stroke="Black"/>
</DataTemplate> </DataTemplate>
<DataTemplate x:Key="BeamShear"> <DataTemplate x:Key="BeamShear">
<Canvas Style="{DynamicResource ButtonResultCanvas}"> <Canvas Style="{DynamicResource ButtonResultCanvas}">
<Canvas.Children> <Canvas.Children>
@@ -168,6 +169,7 @@
</Canvas.Children> </Canvas.Children>
</Canvas> </Canvas>
</DataTemplate> </DataTemplate>
<DataTemplate x:Key="ButtonCalculatorRectangle"> <DataTemplate x:Key="ButtonCalculatorRectangle">
<Rectangle Style="{DynamicResource ButtonRect}" Stroke="{DynamicResource CalculatorFrame}"> <Rectangle Style="{DynamicResource ButtonRect}" Stroke="{DynamicResource CalculatorFrame}">
<Rectangle.Fill> <Rectangle.Fill>

View File

@@ -10,18 +10,18 @@
Title="Shear sections result" Height="450" Width="800" MinHeight="400" MinWidth="600" MaxHeight="900" MaxWidth="1200" WindowStartupLocation="CenterScreen"> Title="Shear sections result" Height="450" Width="800" MinHeight="400" MinWidth="600" MaxHeight="900" MaxWidth="1200" WindowStartupLocation="CenterScreen">
<DockPanel> <DockPanel>
<ToolBarTray DockPanel.Dock="Top"> <ToolBarTray DockPanel.Dock="Top">
<!--<ToolBar Name="Sections"> <ToolBar Name="Sections">
<Button Style="{DynamicResource ToolButton}" Command="{Binding ShowSectionResultsCommand}"> <Button Style="{DynamicResource ToolButton}" Command="{Binding ShowTraceCommand}">
<Button.ToolTip> <Button.ToolTip>
<uc:ButtonToolTipEh HeaderText="Set prestrain" <uc:ButtonToolTipEh HeaderText="Show trace"
IconContent="{StaticResource BeamShear}" IconContent="{StaticResource Report}"
DescriptionText="Set strain from selected combination as auto prestrain (not available if selected result is invalid)"/> DescriptionText="Shows trace for selected inclined section"/>
</Button.ToolTip> </Button.ToolTip>
<Viewbox> <Viewbox>
<ContentControl ContentTemplate="{StaticResource BeamShear}"/> <ContentControl ContentTemplate="{StaticResource Report}"/>
</Viewbox> </Viewbox>
</Button> </Button>
</ToolBar>--> </ToolBar>
</ToolBarTray> </ToolBarTray>
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>

View File

@@ -1,17 +1,21 @@
using StructureHelper.Infrastructure; using StructureHelper.Infrastructure;
using StructureHelper.Windows.CalculationWindows.CalculatorsViews; using StructureHelper.Windows.CalculationWindows.CalculatorsViews;
using StructureHelper.Windows.CalculationWindows.ProgressViews;
using StructureHelperLogics.Models.BeamShears; using StructureHelperLogics.Models.BeamShears;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Input;
namespace StructureHelper.Windows.BeamShears namespace StructureHelper.Windows.BeamShears
{ {
public class BeamShearActionResultViewModel : ViewModelBase public class BeamShearActionResultViewModel : ViewModelBase
{ {
private IBeamShearActionResult result; private IBeamShearActionResult result;
private RelayCommand showTraceCommand;
public IBeamShearSectionLogicResult SelectedResult { get; set; } public IBeamShearSectionLogicResult SelectedResult { get; set; }
public List<IBeamShearSectionLogicResult> SectionResults => result.SectionResults; public List<IBeamShearSectionLogicResult> SectionResults => result.SectionResults;
public ValidResultCounterVM ValidResultCounter { get; } public ValidResultCounterVM ValidResultCounter { get; }
@@ -22,5 +26,13 @@ namespace StructureHelper.Windows.BeamShears
ValidResultCounter = new(this.result.SectionResults); ValidResultCounter = new(this.result.SectionResults);
} }
public ICommand ShowTraceCommand => showTraceCommand ??= new RelayCommand(ShowTrace, o => SelectedResult != null);
private void ShowTrace(object obj)
{
if (SelectedResult.TraceLogger is null) { return; }
var traceWindows = new TraceDocumentView(SelectedResult.TraceLogger);
traceWindows.ShowDialog();
}
} }
} }

View File

@@ -24,24 +24,38 @@
<ColumnDefinition/> <ColumnDefinition/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition Height="25"/>
<RowDefinition Height="25"/> <RowDefinition Height="25"/>
<RowDefinition/> <RowDefinition/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TextBlock Text="Name"/> <TextBlock Text="Name"/>
<TextBox Grid.Column="1" Text="{Binding Name}"/> <TextBox Grid.Column="1" Text="{Binding Name}"/>
<TextBlock Grid.Row="1" Text="Cover to center of rebar"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding CenterCover, Converter={StaticResource LengthConverter}}"/>
</Grid> </Grid>
<!--ShapeEditTemplates.xaml--> <!--ShapeEditTemplates.xaml-->
<ContentControl ContentTemplate="{StaticResource RectangleShapeEdit}" Content="{Binding Shape}"/> <ContentControl ContentTemplate="{StaticResource RectangleShapeEdit}" Content="{Binding Shape}"/>
</StackPanel> </StackPanel>
</TabItem> </TabItem>
<TabItem Header="Material" DataContext="{Binding Material}"> <TabItem Header="Concrete" DataContext="{Binding ConcreteMaterial}">
<!--Material.xaml--> <!--Material.xaml-->
<ContentControl ContentTemplate="{StaticResource ConcreteMaterial}" Content="{Binding}"/> <ContentControl ContentTemplate="{StaticResource ConcreteMaterial}" Content="{Binding}"/>
</TabItem> </TabItem>
<TabItem Header="Reinforcement">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition Height="25"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="Area"/>
<TextBox Grid.Column="1" Text="{Binding ReinforcementArea, Converter={StaticResource AreaConverter}}"/>
<TextBlock Grid.Row="1" Text="Cover to center of rebars"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding CenterCover, Converter={StaticResource LengthConverter}}"/>
<ContentControl Grid.Row="2" Grid.ColumnSpan="2" ContentTemplate="{StaticResource ReinforcementMaterial}" Content="{Binding ReinforcementMaterial}"/>
</Grid>
</TabItem>
</TabControl> </TabControl>
<ContentControl Grid.Row="1" ContentTemplate="{StaticResource OkCancelButtons}" Content="{Binding}"/> <ContentControl Grid.Row="1" ContentTemplate="{StaticResource OkCancelButtons}" Content="{Binding}"/>
</Grid> </Grid>

View File

@@ -2,6 +2,7 @@
using StructureHelper.Windows.ViewModels.Materials; using StructureHelper.Windows.ViewModels.Materials;
using StructureHelperCommon.Models.Shapes; using StructureHelperCommon.Models.Shapes;
using StructureHelperLogics.Models.BeamShears; using StructureHelperLogics.Models.BeamShears;
using System;
//Copyright (c) 2025 Redikultsev Evgeny, Ekaterinburg, Russia //Copyright (c) 2025 Redikultsev Evgeny, Ekaterinburg, Russia
//All rights reserved. //All rights reserved.
@@ -18,6 +19,17 @@ namespace StructureHelper.Windows.BeamShears
set set
{ {
beamShearSection.Name = value; beamShearSection.Name = value;
OnPropertyChanged(nameof(Name));
}
}
public double ReinforcementArea
{
get => beamShearSection.ReinforcementArea;
set
{
value = Math.Max(value, 0);
beamShearSection.ReinforcementArea = value;
OnPropertyChanged(nameof(ReinforcementArea));
} }
} }
public double CenterCover public double CenterCover
@@ -25,20 +37,18 @@ namespace StructureHelper.Windows.BeamShears
get => beamShearSection.CenterCover; get => beamShearSection.CenterCover;
set set
{ {
if (value < 0) value = Math.Max(value, 0);
{
value = 0;
}
beamShearSection.CenterCover = value; beamShearSection.CenterCover = value;
} }
} }
public IRectangleShape Shape { get; } public IRectangleShape Shape { get; }
public ConcreteViewModel Material { get; } public ConcreteViewModel ConcreteMaterial { get; }
public ReinforcementViewModel ReinforcementMaterial { get; }
public SectionViewModel(IBeamShearSection beamShearSection) public SectionViewModel(IBeamShearSection beamShearSection)
{ {
this.beamShearSection = beamShearSection; this.beamShearSection = beamShearSection;
Material = new(beamShearSection.Material) ConcreteMaterial = new(beamShearSection.ConcreteMaterial)
{ {
MaterialLogicVisibility = false, MaterialLogicVisibility = false,
TensionForULSVisibility = false, TensionForULSVisibility = false,
@@ -46,6 +56,7 @@ namespace StructureHelper.Windows.BeamShears
HumidityVisibility = false HumidityVisibility = false
}; };
Shape = beamShearSection.Shape as IRectangleShape; Shape = beamShearSection.Shape as IRectangleShape;
ReinforcementMaterial = new(beamShearSection.ReinforcementMaterial) { MaterialLogicVisibility = false };
} }
} }
} }

View File

@@ -4,6 +4,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StructureHelper.Windows.CalculationWindows.CalculatorsViews" xmlns:local="clr-namespace:StructureHelper.Windows.CalculationWindows.CalculatorsViews"
xmlns:uc="clr-namespace:StructureHelper.Windows.UserControls"
d:DataContext="{d:DesignInstance local:CrackResultViewModel}" d:DataContext="{d:DesignInstance local:CrackResultViewModel}"
mc:Ignorable="d" mc:Ignorable="d"
Title="Result of calculations of crack" Height="450" Width="800" MinHeight="300" MinWidth="600" MaxHeight="800" MaxWidth="1000" WindowStartupLocation="CenterScreen"> Title="Result of calculations of crack" Height="450" Width="800" MinHeight="300" MinWidth="600" MaxHeight="800" MaxWidth="1000" WindowStartupLocation="CenterScreen">
@@ -16,7 +17,7 @@
</Window.Resources> </Window.Resources>
<DockPanel> <DockPanel>
<ToolBarTray DockPanel.Dock="Top"> <ToolBarTray DockPanel.Dock="Top">
<ToolBar> <ToolBar ToolTip="Rebar results">
<Button Style="{DynamicResource ToolButton}" Command="{Binding ShowRebarsCommand}" ToolTip="Show results by rebars"> <Button Style="{DynamicResource ToolButton}" Command="{Binding ShowRebarsCommand}" ToolTip="Show results by rebars">
<Viewbox> <Viewbox>
<ContentControl ContentTemplate="{DynamicResource ShowRebarsResult}"/> <ContentControl ContentTemplate="{DynamicResource ShowRebarsResult}"/>
@@ -28,6 +29,18 @@
</Viewbox> </Viewbox>
</Button> </Button>
</ToolBar> </ToolBar>
<ToolBar ToolTip="Export">
<Button Style="{DynamicResource ToolButton}" Command="{Binding ExportToCSVCommand}">
<Button.ToolTip>
<uc:ButtonToolTipEh HeaderText="Export to *.csv"
IconContent="{StaticResource ExportToXLS}"
DescriptionText="Export all valid results to *.csv file"/>
</Button.ToolTip>
<Viewbox>
<ContentControl ContentTemplate="{DynamicResource ExportToXLS}"/>
</Viewbox>
</Button>
</ToolBar>
</ToolBarTray> </ToolBarTray>
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
@@ -115,26 +128,7 @@
</DataGrid.Columns> </DataGrid.Columns>
</DataGrid> </DataGrid>
<TextBlock Grid.Row="1" Text="{Binding CrackResult.Description}"/> <TextBlock Grid.Row="1" Text="{Binding CrackResult.Description}"/>
<StatusBar Grid.Row="2"> <ContentControl Grid.Row="2" ContentTemplate="{StaticResource ResultValidness}" Content="{Binding ValidResultCounter}"/>
<StatusBarItem>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Valid result(s): "/>
<TextBlock Text="{Binding ValidResultCount}"/>
</StackPanel>
</StatusBarItem>
<StatusBarItem>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Invalid result(s): "/>
<TextBlock Text="{Binding InvalidResultCount}"/>
</StackPanel>
</StatusBarItem>
<StatusBarItem>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Total: "/>
<TextBlock Text="{Binding TotalResultCount}"/>
</StackPanel>
</StatusBarItem>
</StatusBar>
</Grid> </Grid>
</DockPanel> </DockPanel>
</Window> </Window>

View File

@@ -1,10 +1,9 @@
using StructureHelper.Infrastructure; using StructureHelper.Infrastructure;
using StructureHelper.Services.Exports;
using StructureHelperLogics.NdmCalculations.Analyses;
using StructureHelperLogics.NdmCalculations.Cracking; using StructureHelperLogics.NdmCalculations.Cracking;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
namespace StructureHelper.Windows.CalculationWindows.CalculatorsViews namespace StructureHelper.Windows.CalculationWindows.CalculatorsViews
@@ -12,16 +11,14 @@ namespace StructureHelper.Windows.CalculationWindows.CalculatorsViews
public class CrackResultViewModel : ViewModelBase public class CrackResultViewModel : ViewModelBase
{ {
IShowCrackIsoFieldsLogic showCrackIsoFieldsLogic => new ShowCrackIsoFieldsLogic(); IShowCrackIsoFieldsLogic showCrackIsoFieldsLogic => new ShowCrackIsoFieldsLogic();
private CrackResult resultModel; private ICrackResult resultModel;
private RelayCommand? showIsoFieldCommand; private RelayCommand? showIsoFieldCommand;
private RelayCommand? showRebarsCommand; private RelayCommand? showRebarsCommand;
private RelayCommand exportToCSVCommand;
public int ValidResultCount => resultModel.TupleResults.Count(x => x.IsValid == true);
public int InvalidResultCount => resultModel.TupleResults.Count(x => x.IsValid == false);
public int TotalResultCount => resultModel.TupleResults.Count;
public TupleCrackResult SelectedResult { get; set; } public TupleCrackResult SelectedResult { get; set; }
public List<ITupleCrackResult> TupleResults => CrackResult.TupleResults; public List<ITupleCrackResult> TupleResults => CrackResult.TupleResults;
public ValidResultCounterVM ValidResultCounter { get; }
public ICommand ShowRebarsCommand public ICommand ShowRebarsCommand
{ {
get get
@@ -45,11 +42,25 @@ namespace StructureHelper.Windows.CalculationWindows.CalculatorsViews
} }
} }
public CrackResult CrackResult => resultModel; public ICrackResult CrackResult => resultModel;
public CrackResultViewModel(CrackResult crackResult) public CrackResultViewModel(ICrackResult crackResult)
{ {
this.resultModel = crackResult; this.resultModel = crackResult;
ValidResultCounter = new(resultModel.TupleResults);
}
public ICommand ExportToCSVCommand => exportToCSVCommand ??= new RelayCommand(o => { ExportToCSV(); });
private void ExportToCSV()
{
var inputData = new ExportToFileInputData
{
Filter = "csv |*.csv",
Title = "Save in *.csv File"
};
var logic = new ExportCrackResultToCSVLogic(resultModel);
var exportService = new ExportToFileService(inputData, logic);
exportService.Export();
} }
} }
} }

View File

@@ -131,18 +131,7 @@ namespace StructureHelper.Windows.CalculationWindows.CalculatorsViews.ForceCalcu
}, o => SelectedResult != null && SelectedResult.IsValid)); }, o => SelectedResult != null && SelectedResult.IsValid));
} }
} }
public ICommand ExportToCSVCommand public ICommand ExportToCSVCommand => exportToCSVCommand ??= new RelayCommand(o => { ExportToCSV();});
{
get
{
return exportToCSVCommand ??
(exportToCSVCommand = new RelayCommand(o =>
{
ExportToCSV();
}
));
}
}
private void ExportToCSV() private void ExportToCSV()
{ {
var inputData = new ExportToFileInputData var inputData = new ExportToFileInputData

View File

@@ -32,6 +32,12 @@ namespace StructureHelperCommon.Models.Calculators
MaxIterationCount = 1000 MaxIterationCount = 1000
}; };
} }
public FindParameterCalculator(IShiftTraceLogger? traceLogger) : this()
{
TraceLogger = traceLogger;
}
public void Run() public void Run()
{ {
result = new(); result = new();

View File

@@ -1,8 +1,12 @@
using StructureHelperCommon.Infrastructures.Enums; using StructureHelper.Models.Materials;
using StructureHelperCommon.Infrastructures.Enums;
using StructureHelperCommon.Infrastructures.Interfaces; using StructureHelperCommon.Infrastructures.Interfaces;
using StructureHelperCommon.Models; using StructureHelperCommon.Models;
using StructureHelperCommon.Models.Calculators;
using StructureHelperCommon.Models.Forces; using StructureHelperCommon.Models.Forces;
using StructureHelperCommon.Models.Loggers; using StructureHelperCommon.Models.Loggers;
using StructureHelperLogics.Models.Materials;
using StructureHelperLogics.NdmCalculations.Primitives;
namespace StructureHelperLogics.Models.BeamShears namespace StructureHelperLogics.Models.BeamShears
{ {
@@ -27,6 +31,7 @@ namespace StructureHelperLogics.Models.BeamShears
{ {
TraceLogger?.AddMessage(LoggerStrings.LogicType(this), TraceLogStatuses.Service); TraceLogger?.AddMessage(LoggerStrings.LogicType(this), TraceLogStatuses.Service);
this.inputData = inputData; this.inputData = inputData;
PrepareNewResult(); PrepareNewResult();
InitializeStrategies(); InitializeStrategies();
try try
@@ -38,12 +43,35 @@ namespace StructureHelperLogics.Models.BeamShears
{ {
TraceLogger?.AddMessage(ex.Message, TraceLogStatuses.Error); TraceLogger?.AddMessage(ex.Message, TraceLogStatuses.Error);
result.IsValid = false; result.IsValid = false;
result.Description += "\n" + ex.Message;
} }
return result; return result;
} }
private IBeamShearSectionLogicResult CalculateResult(IBeamShearSectionLogicInputData sectionInputData) private void TraceSection(IBeamShearSection section)
{
List<IHeadMaterial> headMaterials = new()
{
new HeadMaterial(Guid.Empty)
{
Name = $"{section.Name}.Concrete",
HelperMaterial = section.ConcreteMaterial
},
new HeadMaterial(Guid.Empty)
{
Name = $"{section.Name}.Reinforcement",
HelperMaterial = section.ReinforcementMaterial
},
};
var traceLogic = new TraceMaterialsFactory()
{
Collection = headMaterials
};
traceLogic.AddEntriesToTraceLogger(TraceLogger);
}
private IBeamShearSectionLogicResult CalculateInclinedSectionResult(IBeamShearSectionLogicInputData sectionInputData)
{ {
beamShearSectionLogic.InputData = sectionInputData; beamShearSectionLogic.InputData = sectionInputData;
beamShearSectionLogic.Run(); beamShearSectionLogic.Run();
@@ -79,6 +107,8 @@ namespace StructureHelperLogics.Models.BeamShears
{ {
foreach (var section in inputData.Sections) foreach (var section in inputData.Sections)
{ {
TraceLogger?.AddMessage($"Analysis for action: {beamShearAction.Name}, section: {section.Name}, calc turm {calcTerm} has been started");
TraceSection(section);
foreach (var stirrup in stirrups) foreach (var stirrup in stirrups)
{ {
List<IInclinedSection> inclinedSections = GetInclinedSections(section); List<IInclinedSection> inclinedSections = GetInclinedSections(section);
@@ -87,6 +117,7 @@ namespace StructureHelperLogics.Models.BeamShears
BeamShearActionResult actionResult = GetActionResult(beamShearAction, calcTerm, section, stirrup, sectionResults); BeamShearActionResult actionResult = GetActionResult(beamShearAction, calcTerm, section, stirrup, sectionResults);
actionResults.Add(actionResult); actionResults.Add(actionResult);
} }
TraceLogger?.AddMessage($"Analysis for action: {beamShearAction.Name}, section: {section.Name}, calc term {calcTerm} has been finished sucessfull");
} }
} }
} }
@@ -113,7 +144,7 @@ namespace StructureHelperLogics.Models.BeamShears
List<IBeamShearSectionLogicResult> sectionResults = new(); List<IBeamShearSectionLogicResult> sectionResults = new();
foreach (var item in sectionInputDatas) foreach (var item in sectionInputDatas)
{ {
IBeamShearSectionLogicResult sectionResult = CalculateResult(item); IBeamShearSectionLogicResult sectionResult = CalculateInclinedSectionResult(item);
sectionResults.Add(sectionResult); sectionResults.Add(sectionResult);
} }
@@ -123,10 +154,12 @@ namespace StructureHelperLogics.Models.BeamShears
private List<IBeamShearSectionLogicInputData> GetSectionInputDatas(IBeamShearAction beamShearAction, CalcTerms calcTerm, IBeamShearSection section, IStirrup stirrup, List<IInclinedSection> inclinedSections) private List<IBeamShearSectionLogicInputData> GetSectionInputDatas(IBeamShearAction beamShearAction, CalcTerms calcTerm, IBeamShearSection section, IStirrup stirrup, List<IInclinedSection> inclinedSections)
{ {
List<IBeamShearSectionLogicInputData> sectionInputDatas = new(); List<IBeamShearSectionLogicInputData> sectionInputDatas = new();
var material = section.Material; var material = section.ConcreteMaterial;
var strength = material.GetStrength(CollapseLimitState, calcTerm); var strength = material.GetStrength(CollapseLimitState, calcTerm);
foreach (var inclinedSection in inclinedSections) foreach (var inclinedSection in inclinedSections)
{ {
inclinedSection.LimitState = CollapseLimitState;
inclinedSection.CalcTerm = calcTerm;
inclinedSection.ConcreteCompressionStrength = strength.Compressive; inclinedSection.ConcreteCompressionStrength = strength.Compressive;
inclinedSection.ConcreteTensionStrength = strength.Tensile; inclinedSection.ConcreteTensionStrength = strength.Tensile;
DirectShearForceLogicInputData inputData = new() DirectShearForceLogicInputData inputData = new()

View File

@@ -10,18 +10,20 @@ namespace StructureHelperLogics.Models.BeamShears
public Guid Id { get; } public Guid Id { get; }
public string? Name { get; set; } public string? Name { get; set; }
/// <inheritdoc/> /// <inheritdoc/>
public IConcreteLibMaterial Material { get; set; } public IConcreteLibMaterial ConcreteMaterial { get; set; }
/// <inheritdoc/> /// <inheritdoc/>
public IShape Shape { get; set; } = new RectangleShape(Guid.NewGuid()) { Height = 0.6, Width = 0.4}; public IShape Shape { get; set; } = new RectangleShape(Guid.NewGuid()) { Height = 0.6, Width = 0.4};
public double CenterCover { get; set; } = 0.05; public double CenterCover { get; set; } = 0.05;
public double ReinforcementArea { get; set; } = 0;
public IReinforcementLibMaterial ReinforcementMaterial { get; set; }
public BeamShearSection(Guid id) public BeamShearSection(Guid id)
{ {
Id = id; Id = id;
Material = ConcreteLibMaterialFactory.GetConcreteLibMaterial(ConcreteLibTypes.Concrete25); ConcreteMaterial = ConcreteLibMaterialFactory.GetConcreteLibMaterial(ConcreteLibTypes.Concrete25);
Material.TensionForULS = true; ReinforcementMaterial = HeadMaterialFactory.GetHeadMaterial(HeadmaterialType.Reinforcement500).HelperMaterial as IReinforcementLibMaterial;
ConcreteMaterial.TensionForULS = true;
} }
public object Clone() public object Clone()

View File

@@ -1,82 +0,0 @@
using StructureHelperCommon.Models;
using StructureHelperCommon.Models.Calculators;
using StructureHelperCommon.Models.Loggers;
using StructureHelperLogics.Models.BeamShears.Logics;
namespace StructureHelperLogics.Models.BeamShears
{
public class BeamShearSectionLogic : IBeamShearSectionLogic
{
private BeamShearSectionLogicResult result;
private ConcreteStrengthLogic concreteLogic;
private StirrupStrengthLogic stirrupLogic;
public IBeamShearSectionLogicInputData InputData { get; set; }
public IShiftTraceLogger? TraceLogger { get; set; }
public BeamShearSectionLogic(IShiftTraceLogger? traceLogger)
{
TraceLogger = traceLogger;
}
public IResult Result => result;
public void Run()
{
TraceLogger?.AddMessage(LoggerStrings.LogicType(this), TraceLogStatuses.Service);
PrepareNewResult();
InitializeStrategies();
try
{
CalculateResult();
}
catch (Exception ex)
{
result.IsValid = false;
result.Description += ex.Message;
}
}
private void CalculateResult()
{
double concreteStrength = concreteLogic.GetShearStrength();
result.ConcreteStrength = concreteStrength;
double stirrupStrength = stirrupLogic.GetShearStrength();
result.StirrupStrength = stirrupStrength;
double totalStrength = concreteStrength + stirrupStrength;
result.TotalStrength = totalStrength;
double actualShearForce = InputData.ForceTuple.Qy;
if (actualShearForce > totalStrength)
{
result.IsValid = false;
string message = $"Actual shear force Qa = {actualShearForce}(N), greater than bearing capacity Olim = {totalStrength}(N)";
result.Description += message;
TraceLogger?.AddMessage(message, TraceLogStatuses.Error);
}
else
{
string message = $"Actual shear force Qa = {actualShearForce}(N), not greater than bearing capacity Olim = {totalStrength}(N)";
TraceLogger?.AddMessage(message);
}
}
private void InitializeStrategies()
{
var sectionEffectiveness = SectionEffectivenessFactory.GetSheaEffectiveness(BeamShearSectionType.Rectangle);
double longitudinalForce = InputData.ForceTuple.Nz;
concreteLogic = new(sectionEffectiveness, InputData.InclinedSection, longitudinalForce, TraceLogger);
stirrupLogic = new(InputData, TraceLogger);
}
private void PrepareNewResult()
{
result = new()
{
IsValid = true,
Description = string.Empty,
InputData = InputData
};
}
}
}

View File

@@ -1,4 +1,5 @@
using System; using StructureHelperCommon.Models;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@@ -15,5 +16,12 @@ namespace StructureHelperLogics.Models.BeamShears
public double StirrupStrength { get; set; } public double StirrupStrength { get; set; }
public double TotalStrength { get; set; } public double TotalStrength { get; set; }
public double FactorOfUsing { get => InputData.ForceTuple.Qy / TotalStrength; } public double FactorOfUsing { get => InputData.ForceTuple.Qy / TotalStrength; }
public IShiftTraceLogger TraceLogger { get; }
public BeamShearSectionLogicResult(IShiftTraceLogger traceLogger)
{
TraceLogger = traceLogger;
}
} }
} }

View File

@@ -13,7 +13,7 @@ namespace StructureHelperLogics.Models.BeamShears
/// <summary> /// <summary>
/// Concrete of cross-section /// Concrete of cross-section
/// </summary> /// </summary>
IConcreteLibMaterial Material { get; set; } IConcreteLibMaterial ConcreteMaterial { get; set; }
/// <summary> /// <summary>
/// Shape of cross-section /// Shape of cross-section
/// </summary> /// </summary>
@@ -22,5 +22,13 @@ namespace StructureHelperLogics.Models.BeamShears
/// Distance from edge of tension zone to center of the nearest reinforcement bar /// Distance from edge of tension zone to center of the nearest reinforcement bar
/// </summary> /// </summary>
double CenterCover { get; set; } double CenterCover { get; set; }
/// <summary>
/// Area of reinforcement in tension zone, m^2
/// </summary>
double ReinforcementArea { get; set; }
/// <summary>
/// Material of reinforcement in tension zone
/// </summary>
IReinforcementLibMaterial ReinforcementMaterial { get; set; }
} }
} }

View File

@@ -1,7 +1,9 @@
using StructureHelperCommon.Models.Calculators; using StructureHelperCommon.Models;
using StructureHelperCommon.Models.Calculators;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Security.Policy;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -14,5 +16,6 @@ namespace StructureHelperLogics.Models.BeamShears
public double StirrupStrength { get; set; } public double StirrupStrength { get; set; }
public double TotalStrength { get; set; } public double TotalStrength { get; set; }
public double FactorOfUsing { get; } public double FactorOfUsing { get; }
public IShiftTraceLogger TraceLogger { get; }
} }
} }

View File

@@ -1,9 +1,5 @@
using StructureHelperCommon.Infrastructures.Interfaces; using StructureHelperCommon.Infrastructures.Enums;
using System; using StructureHelperCommon.Infrastructures.Interfaces;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StructureHelperLogics.Models.BeamShears namespace StructureHelperLogics.Models.BeamShears
{ {
@@ -12,6 +8,18 @@ namespace StructureHelperLogics.Models.BeamShears
/// </summary> /// </summary>
public interface IInclinedSection : IEffectiveDepth public interface IInclinedSection : IEffectiveDepth
{ {
/// <summary>
/// Reference to source beam shear section
/// </summary>
IBeamShearSection BeamShearSection { get; set; }
/// <summary>
/// Type of limite state for calculating
/// </summary>
LimitStates LimitState { get; set; }
/// <summary>
/// Type od calc term for calculating
/// </summary>
CalcTerms CalcTerm { get; set; }
/// <summary> /// <summary>
/// Width of cross-section /// Width of cross-section
/// </summary> /// </summary>

View File

@@ -1,8 +1,4 @@
using System; using StructureHelperCommon.Infrastructures.Enums;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StructureHelperLogics.Models.BeamShears namespace StructureHelperLogics.Models.BeamShears
{ {
@@ -21,5 +17,8 @@ namespace StructureHelperLogics.Models.BeamShears
public double EndCoord { get; set; } public double EndCoord { get; set; }
public double ConcreteCompressionStrength { get; set; } public double ConcreteCompressionStrength { get; set; }
public double ConcreteTensionStrength { get; set; } public double ConcreteTensionStrength { get; set; }
public IBeamShearSection BeamShearSection { get; set; }
public LimitStates LimitState { get; set; }
public CalcTerms CalcTerm { get; set; }
} }
} }

View File

@@ -0,0 +1,142 @@
using StructureHelperCommon.Infrastructures.Exceptions;
using StructureHelperCommon.Infrastructures.Interfaces;
using StructureHelperCommon.Models;
using StructureHelperCommon.Models.Calculators;
using StructureHelperCommon.Models.Loggers;
using StructureHelperLogics.Models.BeamShears.Logics;
namespace StructureHelperLogics.Models.BeamShears
{
public class BeamShearSectionLogic : IBeamShearSectionLogic
{
private BeamShearSectionLogicResult result;
private ISectionEffectiveness sectionEffectiveness;
private ConcreteStrengthLogic concreteLogic;
private StirrupStrengthLogic stirrupLogic;
private IGetLongitudinalForceFactorLogic getLongitudinalForceFactorLogic;
private string sectionMessage;
private ICheckInputDataLogic<IBeamShearSectionLogicInputData> checkInputDataLogic;
private ShiftTraceLogger? localTraceLogger { get; set; }
public IBeamShearSectionLogicInputData InputData { get; set; }
public IShiftTraceLogger? TraceLogger { get; set; }
public BeamShearSectionLogic(IShiftTraceLogger? traceLogger)
{
TraceLogger = traceLogger;
}
public IResult Result => result;
public void Run()
{
TraceLogger?.AddMessage(LoggerStrings.LogicType(this), TraceLogStatuses.Service);
sectionMessage = $"Inclined section: start xstart = {InputData.InclinedSection.StartCoord}(m), end xend = {InputData.InclinedSection.EndCoord}(m). ";
PrepareNewResult();
if (Check() == false) { return; }
localTraceLogger?.AddMessage(sectionMessage);
InitializeStrategies();
try
{
CalculateResult();
}
catch (Exception ex)
{
result.IsValid = false;
result.Description += ex.Message;
}
}
private bool Check()
{
bool checkResult = true;
checkInputDataLogic ??= new CheckSectionLogicInputDataLogic(TraceLogger);
checkInputDataLogic.InputData = InputData;
if (checkInputDataLogic.Check() == false)
{
checkResult = false;
result.IsValid = false;
string errorMessage = checkInputDataLogic.CheckResult;
result.Description += errorMessage;
localTraceLogger?.AddMessage(errorMessage, TraceLogStatuses.Error);
}
return checkResult;
}
private void CalculateResult()
{
SetLongitudinalForce();
double factorOfLongitudinalForce = getLongitudinalForceFactorLogic.GetFactor();
localTraceLogger?.AddMessage($"Factor of longitudinal force = {factorOfLongitudinalForce}, (dimensionless)");
double concreteStrength = concreteLogic.GetShearStrength();
double stirrupStrength = stirrupLogic.GetShearStrength();
if (stirrupStrength > concreteStrength)
{
stirrupStrength = GetStirrupStrengthBySearch();
}
concreteStrength *= factorOfLongitudinalForce;
localTraceLogger?.AddMessage($"Concrete strength Qb = {concreteStrength}(N)");
result.ConcreteStrength = concreteStrength;
stirrupStrength *= factorOfLongitudinalForce;
localTraceLogger?.AddMessage($"Stirrup strength Qsw = {stirrupStrength}(N)");
result.StirrupStrength = stirrupStrength;
double totalStrength = concreteStrength + stirrupStrength;
localTraceLogger?.AddMessage($"Total strength = {concreteStrength} + {stirrupStrength} = {totalStrength}(N)");
result.TotalStrength = totalStrength;
double actualShearForce = InputData.ForceTuple.Qy;
if (actualShearForce > totalStrength)
{
result.IsValid = false;
string message = $"Actual shear force Qa = {actualShearForce}(N), greater than bearing capacity Olim = {totalStrength}(N)";
result.Description += message;
localTraceLogger?.AddMessage(message, TraceLogStatuses.Error);
TraceLogger?.AddMessage(sectionMessage + message, TraceLogStatuses.Error);
}
else
{
string message = $"Actual shear force Qa = {actualShearForce}(N), not greater than bearing capacity Olim = {totalStrength}(N)";
localTraceLogger?.AddMessage(message);
TraceLogger?.AddMessage(sectionMessage + message);
}
}
private double GetStirrupStrengthBySearch()
{
var logic = new StirrupBySearchLogic(TraceLogger)
{
InputData = InputData,
SectionEffectiveness = sectionEffectiveness
};
double stirrupStrength = logic.GetShearStrength();
localTraceLogger?.AddMessage($"Stirrup strength was restricted as Qsw,restricted = {stirrupStrength}(N)");
return stirrupStrength;
}
private void InitializeStrategies()
{
sectionEffectiveness = SectionEffectivenessFactory.GetSheaEffectiveness(BeamShearSectionType.Rectangle);
concreteLogic = new(sectionEffectiveness, InputData.InclinedSection, localTraceLogger);
stirrupLogic = new(InputData, localTraceLogger);
getLongitudinalForceFactorLogic = new GetLongitudinalForceFactorLogic(localTraceLogger?.GetSimilarTraceLogger(100));
}
private void SetLongitudinalForce()
{
getLongitudinalForceFactorLogic.LongitudinalForce = InputData.ForceTuple.Nz;
getLongitudinalForceFactorLogic.InclinedSection = InputData.InclinedSection;
}
private void PrepareNewResult()
{
localTraceLogger = new();
result = new(localTraceLogger)
{
IsValid = true,
Description = string.Empty,
InputData = InputData,
};
}
}
}

View File

@@ -15,6 +15,7 @@ namespace StructureHelperLogics.Models.BeamShears
{ {
private IUpdateStrategy<IShape> shapeUpdateStrategy; private IUpdateStrategy<IShape> shapeUpdateStrategy;
private IUpdateStrategy<IConcreteLibMaterial> concreteUpdateStrategy; private IUpdateStrategy<IConcreteLibMaterial> concreteUpdateStrategy;
private IUpdateStrategy<IReinforcementLibMaterial> reinforcementUpdateStrategy;
public void Update(IBeamShearSection targetObject, IBeamShearSection sourceObject) public void Update(IBeamShearSection targetObject, IBeamShearSection sourceObject)
{ {
CheckObject.IsNull(targetObject); CheckObject.IsNull(targetObject);
@@ -22,9 +23,12 @@ namespace StructureHelperLogics.Models.BeamShears
if (ReferenceEquals(targetObject, sourceObject)) { return; } if (ReferenceEquals(targetObject, sourceObject)) { return; }
InitializeStrategies(); InitializeStrategies();
targetObject.Name = sourceObject.Name; targetObject.Name = sourceObject.Name;
targetObject.ReinforcementArea = sourceObject.ReinforcementArea;
shapeUpdateStrategy.Update(targetObject.Shape, sourceObject.Shape); shapeUpdateStrategy.Update(targetObject.Shape, sourceObject.Shape);
targetObject.Material ??= new ConcreteLibMaterial(); targetObject.ConcreteMaterial ??= new ConcreteLibMaterial();
concreteUpdateStrategy.Update(targetObject.Material, sourceObject.Material); concreteUpdateStrategy.Update(targetObject.ConcreteMaterial, sourceObject.ConcreteMaterial);
targetObject.ReinforcementMaterial ??= new ReinforcementLibMaterial(Guid.NewGuid());
reinforcementUpdateStrategy.Update(targetObject.ReinforcementMaterial, sourceObject.ReinforcementMaterial);
targetObject.CenterCover = sourceObject.CenterCover; targetObject.CenterCover = sourceObject.CenterCover;
} }
@@ -32,6 +36,7 @@ namespace StructureHelperLogics.Models.BeamShears
{ {
shapeUpdateStrategy ??= new ShapeUpdateStrategy(); shapeUpdateStrategy ??= new ShapeUpdateStrategy();
concreteUpdateStrategy ??= new ConcreteLibUpdateStrategy(); concreteUpdateStrategy ??= new ConcreteLibUpdateStrategy();
reinforcementUpdateStrategy ??= new ReinforcementLibUpdateStrategy();
} }
} }
} }

View File

@@ -35,7 +35,7 @@ namespace StructureHelperLogics.Models.BeamShears.Logics
} }
else else
{ {
if (Entity.Material is null) if (Entity.ConcreteMaterial is null)
{ {
result = false; result = false;
TraceMessage($"\nMaterial of cross-section is not assigned"); TraceMessage($"\nMaterial of cross-section is not assigned");

View File

@@ -0,0 +1,50 @@
using StructureHelperCommon.Infrastructures.Exceptions;
using StructureHelperCommon.Infrastructures.Interfaces;
using StructureHelperCommon.Models;
namespace StructureHelperLogics.Models.BeamShears
{
internal class CheckSectionLogicInputDataLogic : ICheckInputDataLogic<IBeamShearSectionLogicInputData>
{
private bool result;
private string checkResult;
public CheckSectionLogicInputDataLogic(IShiftTraceLogger? traceLogger)
{
TraceLogger = traceLogger;
}
public IBeamShearSectionLogicInputData InputData { get; set; }
public string CheckResult => checkResult;
public IShiftTraceLogger? TraceLogger { get; set; }
public bool Check()
{
result = true;
checkResult = string.Empty;
if (InputData is null)
{
result = false;
string errorString = ErrorStrings.ParameterIsNull + ": Input data";
throw new StructureHelperException(errorString);
}
if (InputData.ForceTuple is null)
{
result = false;
TraceMessage("Force tuple is null");
}
if (InputData.ForceTuple.Qy < 0)
{
result = false;
TraceMessage($"Shear force Qy = {InputData.ForceTuple.Qy} must be positive");
}
return result;
}
private void TraceMessage(string errorString)
{
checkResult += errorString;
TraceLogger?.AddMessage(errorString);
}
}
}

View File

@@ -6,22 +6,19 @@ namespace StructureHelperLogics.Models.BeamShears
{ {
public class ConcreteStrengthLogic : IBeamShearStrenghLogic public class ConcreteStrengthLogic : IBeamShearStrenghLogic
{ {
private readonly double longitudinalForce;
private readonly ISectionEffectiveness sectionEffectiveness; private readonly ISectionEffectiveness sectionEffectiveness;
private readonly IInclinedSection inclinedSection; private readonly IInclinedSection inclinedSection;
private IGetLongitudinalForceFactorLogic getLongitudinalForceFactorLogic;
private double crackLength; private double crackLength;
public ConcreteStrengthLogic( public ConcreteStrengthLogic(
ISectionEffectiveness sectionEffectiveness, ISectionEffectiveness sectionEffectiveness,
IInclinedSection inclinedSection, IInclinedSection inclinedSection,
double longitudinalForce,
IShiftTraceLogger? traceLogger) IShiftTraceLogger? traceLogger)
{ {
this.sectionEffectiveness = sectionEffectiveness; this.sectionEffectiveness = sectionEffectiveness;
this.inclinedSection = inclinedSection; this.inclinedSection = inclinedSection;
this.longitudinalForce = longitudinalForce;
TraceLogger = traceLogger; TraceLogger = traceLogger;
} }
@@ -35,27 +32,29 @@ namespace StructureHelperLogics.Models.BeamShears
TraceLogger?.AddMessage($"Section shape factor = {sectionEffectiveness.ShapeFactor}, (dimensionless)"); TraceLogger?.AddMessage($"Section shape factor = {sectionEffectiveness.ShapeFactor}, (dimensionless)");
TraceLogger?.AddMessage($"Effective depth = {inclinedSection.EffectiveDepth}, (m)"); TraceLogger?.AddMessage($"Effective depth = {inclinedSection.EffectiveDepth}, (m)");
crackLength = inclinedSection.EndCoord - inclinedSection.StartCoord; crackLength = inclinedSection.EndCoord - inclinedSection.StartCoord;
TraceLogger?.AddMessage($"Crack length = {inclinedSection.EndCoord} - {inclinedSection.StartCoord} = {crackLength}, (m)"); TraceLogger?.AddMessage($"Absolute crack length c = {inclinedSection.EndCoord} - {inclinedSection.StartCoord} = {crackLength}, (m)");
TraceLogger?.AddMessage($"Relative crack length c/d = {crackLength} / {inclinedSection.EffectiveDepth} = {crackLength/ inclinedSection.EffectiveDepth},(dimensionless)");
RestrictCrackLength(); RestrictCrackLength();
SetLongitudinalForce();
double factorOfLongitudinalForce = getLongitudinalForceFactorLogic.GetFactor();
TraceLogger?.AddMessage($"Factor of longitudinal force = {factorOfLongitudinalForce}, (dimensionless)"); double concreteMoment =
double concreteMoment = sectionEffectiveness.BaseShapeFactor * sectionEffectiveness.ShapeFactor * inclinedSection.ConcreteTensionStrength * inclinedSection.WebWidth * inclinedSection.EffectiveDepth * inclinedSection.EffectiveDepth; sectionEffectiveness.BaseShapeFactor
double shearStrength = factorOfLongitudinalForce * concreteMoment / crackLength; * sectionEffectiveness.ShapeFactor
TraceLogger?.AddMessage($"Shear strength of concrete = {shearStrength}, (N)"); * inclinedSection.ConcreteTensionStrength
* inclinedSection.WebWidth
* inclinedSection.EffectiveDepth
* inclinedSection.EffectiveDepth;
double shearStrength = concreteMoment / crackLength;
TraceLogger?.AddMessage($"Shear strength of concrete = {sectionEffectiveness.BaseShapeFactor} * {sectionEffectiveness.ShapeFactor} * {inclinedSection.ConcreteTensionStrength} * {inclinedSection.WebWidth} * {inclinedSection.EffectiveDepth} ^ 2 / {crackLength} = {shearStrength}, (N)");
return shearStrength; return shearStrength;
} }
private void InitializeStrategies() private void InitializeStrategies()
{ {
getLongitudinalForceFactorLogic ??= new GetLongitudinalForceFactorLogic(TraceLogger?.GetSimilarTraceLogger(100));
} }
private void SetLongitudinalForce()
{
getLongitudinalForceFactorLogic.LongitudinalForce = longitudinalForce;
getLongitudinalForceFactorLogic.InclinedSection = inclinedSection;
}
private void RestrictCrackLength() private void RestrictCrackLength()
{ {

View File

@@ -41,6 +41,7 @@ namespace StructureHelperLogics.Models.BeamShears
effectiveDepth = depth - beamShearSection.CenterCover; effectiveDepth = depth - beamShearSection.CenterCover;
inclinedSection = new() inclinedSection = new()
{ {
BeamShearSection = beamShearSection,
FullDepth = depth, FullDepth = depth,
EffectiveDepth = effectiveDepth, EffectiveDepth = effectiveDepth,
StartCoord = startCoord, StartCoord = startCoord,

View File

@@ -7,10 +7,13 @@ namespace StructureHelperLogics.Models.BeamShears.Logics
{ {
public class GetLongitudinalForceFactorLogic : IGetLongitudinalForceFactorLogic public class GetLongitudinalForceFactorLogic : IGetLongitudinalForceFactorLogic
{ {
private const double fstRatioInCompression = 0.25; private const double sndRatioInCompression = 0.5;
private const double sndRatioInCompression = 0.75; private const double maxFactor = 1.25;
private double sectionArea; private double sectionArea;
private ShiftTraceLogger localTraceLogger;
private ICheckEntityLogic<IInclinedSection> checkInclinedSectionLogic; private ICheckEntityLogic<IInclinedSection> checkInclinedSectionLogic;
private IGetReducedAreaLogic getReducedAreaLogic;
public IShiftTraceLogger? TraceLogger { get; set; } public IShiftTraceLogger? TraceLogger { get; set; }
public IInclinedSection InclinedSection { get; set; } public IInclinedSection InclinedSection { get; set; }
@@ -21,39 +24,62 @@ namespace StructureHelperLogics.Models.BeamShears.Logics
TraceLogger = traceLogger; TraceLogger = traceLogger;
} }
public GetLongitudinalForceFactorLogic(
ICheckEntityLogic<IInclinedSection> checkInclinedSectionLogic,
IGetReducedAreaLogic getReducedAreaLogic,
IShiftTraceLogger? traceLogger)
{
this.checkInclinedSectionLogic = checkInclinedSectionLogic;
this.getReducedAreaLogic = getReducedAreaLogic;
TraceLogger = traceLogger;
}
public double GetFactor() public double GetFactor()
{ {
TraceLogger?.AddMessage(LoggerStrings.LogicType(this), TraceLogStatuses.Service); localTraceLogger = new();
TraceLogger?.AddMessage("Logic of calculating of factor of influence of longitudinal force according to SP 63.13330.2018"); localTraceLogger.AddMessage(LoggerStrings.LogicType(this), TraceLogStatuses.Service);
localTraceLogger.AddMessage("Logic of calculating of factor of influence of longitudinal force according to SP 63.13330.2018");
Check(); Check();
double result;
if (LongitudinalForce == 0) if (LongitudinalForce == 0)
{ {
TraceLogger?.AddMessage("Longitudinal force is zero", TraceLogStatuses.Service); localTraceLogger.AddMessage("Longitudinal force is zero", TraceLogStatuses.Service);
return 1; result = 1;
}
sectionArea = InclinedSection.WebWidth * InclinedSection.FullDepth;
TraceLogger?.AddMessage($"Area of cross-section Ac = {InclinedSection.WebWidth} * {InclinedSection.FullDepth} = {sectionArea}(m^2)");
if (LongitudinalForce < 0)
{
TraceLogger?.AddMessage($"Longitudinal force N={LongitudinalForce}(N) is negative (compression)", TraceLogStatuses.Service);
return GetNegForceResult();
} }
else else
{ {
TraceLogger?.AddMessage($"Longitudinal force N={LongitudinalForce}(N) is positive (tension)", TraceLogStatuses.Service); result = GetFactorByForce();
return GetPosForceResult();
} }
localTraceLogger.TraceLoggerEntries.ForEach(x => TraceLogger?.TraceLoggerEntries.Add(x));
return result;
}
private double GetFactorByForce()
{
double result;
getReducedAreaLogic ??= new GetReducedAreaLogicSP63_2018_rev3(LongitudinalForce, InclinedSection, localTraceLogger);
sectionArea = getReducedAreaLogic.GetArea();
if (LongitudinalForce < 0)
{
localTraceLogger.AddMessage($"Longitudinal force N={LongitudinalForce}(N) is negative (compression)", TraceLogStatuses.Service);
result = GetNegForceResult();
}
else
{
localTraceLogger.AddMessage($"Longitudinal force N={LongitudinalForce}(N) is positive (tension)", TraceLogStatuses.Service);
result = GetPosForceResult();
}
return result;
} }
private void Check() private void Check()
{ {
checkInclinedSectionLogic ??= new CheckInclinedSectionLogic(TraceLogger); checkInclinedSectionLogic ??= new CheckInclinedSectionLogic(localTraceLogger);
checkInclinedSectionLogic.Entity = InclinedSection; checkInclinedSectionLogic.Entity = InclinedSection;
if (checkInclinedSectionLogic.Check() == false) if (checkInclinedSectionLogic.Check() == false)
{ {
string errorString = checkInclinedSectionLogic.CheckResult; string errorString = checkInclinedSectionLogic.CheckResult;
TraceLogger?.AddMessage(errorString, TraceLogStatuses.Error); localTraceLogger.AddMessage(errorString, TraceLogStatuses.Error);
throw new StructureHelperException(errorString); throw new StructureHelperException(errorString);
} }
} }
@@ -61,41 +87,43 @@ namespace StructureHelperLogics.Models.BeamShears.Logics
private double GetPosForceResult() private double GetPosForceResult()
{ {
double stressInConcrete = LongitudinalForce / sectionArea; double stressInConcrete = LongitudinalForce / sectionArea;
TraceLogger?.AddMessage($"Average stress in concrete (positive in tension) Sigma = {LongitudinalForce}(N) / {sectionArea}(m^2) = {stressInConcrete}(Pa)"); localTraceLogger.AddMessage($"Average stress in concrete (positive in tension) Sigma = {LongitudinalForce}(N) / {sectionArea}(m^2) = {stressInConcrete}(Pa)");
double concreteStrength = InclinedSection.ConcreteTensionStrength; double concreteStrength = InclinedSection.ConcreteTensionStrength;
TraceLogger?.AddMessage($"Concrete strength Rbt = {concreteStrength}(Pa)"); localTraceLogger.AddMessage($"Concrete strength Rbt = {concreteStrength}(Pa)");
double stressRatio = stressInConcrete / concreteStrength; double stressRatio = stressInConcrete / concreteStrength;
TraceLogger?.AddMessage($"Stress ratio rt = {stressInConcrete} / {concreteStrength} = {stressRatio}(dimensionless)"); localTraceLogger.AddMessage($"Stress ratio rt = {stressInConcrete} / {concreteStrength} = {stressRatio}(dimensionless)");
double factor = 1 - 0.5 * stressRatio; double factor = 1 - 0.5 * stressRatio;
factor = Math.Max(factor, 0); factor = Math.Max(factor, 0);
TraceLogger?.AddMessage($"Factor value fi_n = {factor}(dimensionless)"); localTraceLogger.AddMessage($"Factor value fi_n = {factor}(dimensionless)");
return factor; return factor;
} }
private double GetNegForceResult() private double GetNegForceResult()
{ {
double stressInConcrete = (-1) * LongitudinalForce / sectionArea; double stressInConcrete = (-1) * LongitudinalForce / sectionArea;
TraceLogger?.AddMessage($"Average stress in concrete (positive in compression) Sigma = {LongitudinalForce}(N) / {sectionArea}(m^2) = {stressInConcrete}(Pa)"); localTraceLogger.AddMessage($"Average stress in concrete (positive in compression) Sigma = {LongitudinalForce}(N) / {sectionArea}(m^2) = {stressInConcrete}(Pa)");
double concreteStrength = InclinedSection.ConcreteCompressionStrength; double concreteStrength = InclinedSection.ConcreteCompressionStrength;
TraceLogger?.AddMessage($"Concrete strength Rb = {concreteStrength}(Pa)"); localTraceLogger.AddMessage($"Concrete strength Rb = {concreteStrength}(Pa)");
double stressRatio = stressInConcrete / concreteStrength; double stressRatio = stressInConcrete / concreteStrength;
TraceLogger?.AddMessage($"Stress ratio rc = {stressInConcrete} / {concreteStrength} = {stressRatio}(dimensionless)"); localTraceLogger.AddMessage($"Stress ratio rc = {stressInConcrete} / {concreteStrength} = {stressRatio}(dimensionless)");
double factor; double factor;
double fstRatioInCompression = maxFactor-1;
if (stressRatio < fstRatioInCompression) if (stressRatio < fstRatioInCompression)
{ {
TraceLogger?.AddMessage($"Stress ratio rc = {stressRatio} < {fstRatioInCompression}"); localTraceLogger.AddMessage($"Stress ratio rc = {stressRatio} < {fstRatioInCompression}");
factor = 1 + stressRatio; factor = 1 + stressRatio;
} }
else if (stressRatio > sndRatioInCompression) else if (stressRatio > sndRatioInCompression)
{ {
factor = 5 * (1 - stressRatio); double stressFactor = maxFactor / (1 - sndRatioInCompression);
factor = stressFactor * (1 - stressRatio);
factor = Math.Max(factor, 0); factor = Math.Max(factor, 0);
} }
else else
{ {
factor = 1 + fstRatioInCompression; factor = maxFactor;
} }
TraceLogger?.AddMessage($"Factor value fi_n = {factor}(dimensionless)"); localTraceLogger.AddMessage($"Factor value fi_n = {factor}(dimensionless)");
return factor; return factor;
} }
} }

View File

@@ -0,0 +1,119 @@
using StructureHelperCommon.Models;
using StructureHelperCommon.Models.Loggers;
namespace StructureHelperLogics.Models.BeamShears
{
public class GetReducedAreaLogicSP63_2018_rev3 : IGetReducedAreaLogic
{
private const double epsilon_b0 = 0.002;
private const double epsilon_bt0 = 0.0001;
private double longitudinalForce;
private IInclinedSection inclinedSection;
private (double Compressive, double Tensile) concreteStrength;
private double reinforcementModulus;
private double concreteModulus;
private double reducingFactor;
private double concreteArea;
private double reinforcementArea;
public IShiftTraceLogger? TraceLogger { get; set; }
public GetReducedAreaLogicSP63_2018_rev3(double longitudinalForce, IInclinedSection inclinedSection, IShiftTraceLogger? traceLogger)
{
this.longitudinalForce = longitudinalForce;
this.inclinedSection = inclinedSection;
TraceLogger = traceLogger;
}
public double GetArea()
{
TraceLogger?.AddMessage(LoggerStrings.LogicType(this), TraceLogStatuses.Service);
TraceLogger?.AddMessage($"Calculting of reduced area of cross-section according to SP 63.13330.2018 rev.3");
GetSuplimentaryParemeters();
double area = GetReducedArea();
return area;
}
private double GetReducedArea()
{
if (longitudinalForce <= 0)
{
TraceLogger?.AddMessage($"Longitudinal force Nz = {longitudinalForce} is negative, section under compression");
return GetNegForceArea();
}
else
{
TraceLogger?.AddMessage($"Longitudinal force Nz = {longitudinalForce} is positive, section under tension");
return GetPosForceArea();
}
}
private void GetSuplimentaryParemeters()
{
GetConcreteModulus();
GetReinforcementModulus();
GetConcreteStrength();
GetAreas();
}
private double GetPosForceArea()
{
double tensileStrength = concreteStrength.Tensile;
TraceLogger?.AddMessage($"Modulus of elasticity of reinforcement Es = {reinforcementModulus }(Pa)");
TraceLogger?.AddMessage($"Modulus of elasticity of concrete Eb = {concreteModulus }(Pa)");
TraceLogger?.AddMessage($"Ratio of modulus of elasticity alpha = {reducingFactor }(dimensionless)");
TraceLogger?.AddMessage($"Tensile strength of concrete Rbt = {tensileStrength }(Pa)");
TraceLogger?.AddMessage($"Reference strain of concrete Epsilonbt0 = {epsilon_bt0 }(dimensionless)");
double factorOfInelasticity = tensileStrength / (epsilon_bt0 * concreteModulus);
TraceLogger?.AddMessage($"Factor of inelastisity nu = Rbt / (Epsilon_bt0 * Eb) = {tensileStrength } / ({epsilon_bt0} * {concreteModulus}) = {factorOfInelasticity}(dimensionless)");
double factor = reducingFactor / factorOfInelasticity;
double area = concreteArea + reinforcementArea * factor;
TraceLogger?.AddMessage($"Reduced area Ared = {concreteArea} + {reducingFactor} / {factorOfInelasticity} * {reinforcementArea} = {area}(m^2)");
return area;
}
private double GetNegForceArea()
{
double compressiveStrength = concreteStrength.Compressive;
TraceLogger?.AddMessage($"Modulus of elasticity of reinforcement Es = {reinforcementModulus }(Pa)");
TraceLogger?.AddMessage($"Modulus of elasticity of concrete Eb = {concreteModulus }(Pa)");
TraceLogger?.AddMessage($"Ratio of modulus of elasticity alpha = {reducingFactor }(dimensionless)");
TraceLogger?.AddMessage($"Compressive strength of concrete Rb = {compressiveStrength }(Pa)");
TraceLogger?.AddMessage($"Reference strain of concrete Epsilonb0 = {epsilon_b0 }(dimensionless)");
double factorOfInelasticity = compressiveStrength / (epsilon_b0 * concreteModulus);
TraceLogger?.AddMessage($"Factor of inelastisity nu = Rb / (Epsilon_b0 * Eb) = {compressiveStrength } / ({epsilon_b0} * {concreteModulus}) = {factorOfInelasticity}(dimensionless)");
double factor = reducingFactor / factorOfInelasticity;
double area = concreteArea + reinforcementArea * factor;
TraceLogger?.AddMessage($"Reduced area Ared = {concreteArea} + {reducingFactor} / {factorOfInelasticity} * {reinforcementArea} = {area}(m^2)");
return area;
}
private void GetAreas()
{
reducingFactor = reinforcementModulus / concreteModulus;
concreteArea = inclinedSection.WebWidth * inclinedSection.FullDepth;
TraceLogger?.AddMessage($"Concrete area Ac = {concreteArea}(m^2)");
reinforcementArea = inclinedSection.BeamShearSection.ReinforcementArea;
TraceLogger?.AddMessage($"Reinforcement area As = {reinforcementArea}(m^2)");
}
private void GetConcreteModulus()
{
var concreteMaterial = inclinedSection.BeamShearSection.ConcreteMaterial;
var loaderMaterial = concreteMaterial.GetLoaderMaterial(inclinedSection.LimitState, inclinedSection.CalcTerm);
concreteModulus = loaderMaterial.InitModulus;
}
private void GetReinforcementModulus()
{
var reinforcementMaterial = inclinedSection.BeamShearSection.ReinforcementMaterial;
var loaderMaterial = reinforcementMaterial.GetLoaderMaterial(inclinedSection.LimitState, inclinedSection.CalcTerm);
reinforcementModulus = loaderMaterial.InitModulus;
}
private void GetConcreteStrength()
{
concreteStrength = inclinedSection.BeamShearSection.ConcreteMaterial.GetStrength(inclinedSection.LimitState, inclinedSection.CalcTerm);
}
}
}

View File

@@ -5,7 +5,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace StructureHelperLogics.Models.BeamShears.Logics namespace StructureHelperLogics.Models.BeamShears
{ {
/// <summary> /// <summary>
/// Implement logic for calculation of bearing capacity of inclined section for shear /// Implement logic for calculation of bearing capacity of inclined section for shear

View File

@@ -1,12 +1,8 @@
using System; using StructureHelperCommon.Models.Calculators;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StructureHelperLogics.Models.BeamShears namespace StructureHelperLogics.Models.BeamShears
{ {
public interface IGetInclinedSectionListInputData public interface IGetInclinedSectionListInputData : IInputData
{ {
int StepCount { get; set; } int StepCount { get; set; }
double MaxInclinedSectionLegthFactor { get; set; } double MaxInclinedSectionLegthFactor { get; set; }

View File

@@ -1,9 +1,4 @@
using StructureHelperCommon.Infrastructures.Interfaces; using StructureHelperCommon.Infrastructures.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StructureHelperLogics.Models.BeamShears namespace StructureHelperLogics.Models.BeamShears
{ {

View File

@@ -0,0 +1,9 @@
using StructureHelperCommon.Infrastructures.Interfaces;
namespace StructureHelperLogics.Models.BeamShears
{
public interface IGetReducedAreaLogic : ILogic
{
double GetArea();
}
}

View File

@@ -0,0 +1,26 @@
using StructureHelperCommon.Infrastructures.Exceptions;
using StructureHelperCommon.Infrastructures.Interfaces;
using StructureHelperCommon.Services;
namespace StructureHelperLogics.Models.BeamShears
{
internal class InclinedSectionUpdateStrategy : IUpdateStrategy<IInclinedSection>
{
public void Update(IInclinedSection targetObject, IInclinedSection sourceObject)
{
CheckObject.IsNull(sourceObject, ErrorStrings.SourceObject);
CheckObject.IsNull(targetObject, ErrorStrings.TargetObject);
if (ReferenceEquals(targetObject, sourceObject)) { return; };
targetObject.StartCoord = sourceObject.StartCoord;
targetObject.EndCoord = sourceObject.EndCoord;
targetObject.EffectiveDepth = sourceObject.EffectiveDepth;
targetObject.FullDepth = sourceObject.FullDepth;
targetObject.LimitState = sourceObject.LimitState;
targetObject.CalcTerm = sourceObject.CalcTerm;
targetObject.ConcreteCompressionStrength = sourceObject.ConcreteCompressionStrength;
targetObject.ConcreteTensionStrength = sourceObject.ConcreteTensionStrength;
targetObject.WebWidth = sourceObject.WebWidth;
targetObject.BeamShearSection = sourceObject.BeamShearSection.Clone() as IBeamShearSection;
}
}
}

View File

@@ -43,11 +43,11 @@ namespace StructureHelperLogics.Models.BeamShears
double finalCrackLength = Math.Min(crackLength, maxCrackLength); double finalCrackLength = Math.Min(crackLength, maxCrackLength);
TraceLogger?.AddMessage($"Length of crack = Min({crackLength}, {maxCrackLength}) = {finalCrackLength}(m)"); TraceLogger?.AddMessage($"Length of crack = Min({crackLength}, {maxCrackLength}) = {finalCrackLength}(m)");
double finalDensity = stirrupEffectiveness.StirrupShapeFactor * stirrupEffectiveness.StirrupPlacementFactor * stirrupByDensity.StirrupDensity; double finalDensity = stirrupEffectiveness.StirrupShapeFactor * stirrupEffectiveness.StirrupPlacementFactor * stirrupByDensity.StirrupDensity;
TraceLogger?.AddMessage($"Stirrups design density qsw = {finalDensity}(N/m)"); TraceLogger?.AddMessage($"Stirrups design density qsw = {stirrupEffectiveness.StirrupShapeFactor} * {stirrupEffectiveness.StirrupPlacementFactor} * {stirrupByDensity.StirrupDensity} = {finalDensity}(N/m)");
double concreteDensity = inclinedSection.WebWidth * inclinedSection.ConcreteTensionStrength; double concreteDensity = inclinedSection.WebWidth * inclinedSection.ConcreteTensionStrength;
if (finalDensity < minStirrupRatio * concreteDensity) if (finalDensity < minStirrupRatio * concreteDensity)
{ {
TraceLogger?.AddMessage($"Since stirrups design density qsw = {finalDensity}(N/m) less than {minStirrupRatio} * {concreteDensity}, final density is equal to zero"); TraceLogger?.AddMessage($"Since stirrups design density qsw = {finalDensity}(N/m) less than {minStirrupRatio} * {concreteDensity}, final density is equal to zero", TraceLogStatuses.Warning);
finalDensity = 0; finalDensity = 0;
} }
double strength = finalDensity * finalCrackLength; double strength = finalDensity * finalCrackLength;

View File

@@ -5,7 +5,7 @@ using StructureHelperCommon.Models.Forces;
//Copyright (c) 2025 Redikultsev Evgeny, Ekaterinburg, Russia //Copyright (c) 2025 Redikultsev Evgeny, Ekaterinburg, Russia
//All rights reserved. //All rights reserved.
namespace StructureHelperLogics.Models.BeamShears.Logics namespace StructureHelperLogics.Models.BeamShears
{ {
public class StirrupByRebarStrengthLogic : IBeamShearStrenghLogic public class StirrupByRebarStrengthLogic : IBeamShearStrenghLogic
{ {
@@ -52,9 +52,15 @@ namespace StructureHelperLogics.Models.BeamShears.Logics
public double GetShearStrength() public double GetShearStrength()
{ {
InitializeStrategies(); InitializeStrategies();
TraceLogger?.AddMessage($"Stirrup diameter d = {stirrupByRebar.Diameter}(m)");
TraceLogger?.AddMessage($"Stirrup leg number n = {stirrupByRebar.LegCount}");
TraceLogger?.AddMessage($"Stirrup spacing S = {stirrupByRebar.Spacing}(m)");
double maxSpacingRatio = inclinedSection.ConcreteTensionStrength * inclinedSection.WebWidth * inclinedSection.EffectiveDepth / forceTuple.Qy; double maxSpacingRatio = inclinedSection.ConcreteTensionStrength * inclinedSection.WebWidth * inclinedSection.EffectiveDepth / forceTuple.Qy;
TraceLogger?.AddMessage($"Maximum spacing ratio due to strength beetwen hoops Sr,max = {maxSpacingRatio}(dimensionless)");
maxSpacingRatio = Math.Min(maxSpacingRatio, 0.5); maxSpacingRatio = Math.Min(maxSpacingRatio, 0.5);
TraceLogger?.AddMessage($"Maximum spacing ratio Sr,max = {maxSpacingRatio}(dimensionless)");
double maxStirrupSpacingByEffectibeDepth = maxSpacingRatio * inclinedSection.EffectiveDepth; double maxStirrupSpacingByEffectibeDepth = maxSpacingRatio * inclinedSection.EffectiveDepth;
TraceLogger?.AddMessage($"Maximum spacing S,max = {maxStirrupSpacingByEffectibeDepth}(m)");
if (stirrupByRebar.Spacing > maxStirrupSpacingByEffectibeDepth) if (stirrupByRebar.Spacing > maxStirrupSpacingByEffectibeDepth)
{ {
TraceLogger?.AddMessage($"Stirrup spacing S = {stirrupByRebar.Spacing}(m) is greater than max stirrup spacing Smax = {maxStirrupSpacingByEffectibeDepth}(m), stirrups are ignored", TraceLogStatuses.Warning); TraceLogger?.AddMessage($"Stirrup spacing S = {stirrupByRebar.Spacing}(m) is greater than max stirrup spacing Smax = {maxStirrupSpacingByEffectibeDepth}(m), stirrups are ignored", TraceLogStatuses.Warning);

View File

@@ -6,9 +6,8 @@ namespace StructureHelperLogics.Models.BeamShears
{ {
public class StirrupByRebarToDensityConvertStrategy : IConvertStrategy<IStirrupByDensity, IStirrupByRebar> public class StirrupByRebarToDensityConvertStrategy : IConvertStrategy<IStirrupByDensity, IStirrupByRebar>
{ {
private const double stirrupStrengthFactor = 1d; private const double stirrupStrengthFactor = 0.8d;
private const double maxStirrupStrength = 3e8; private const double maxStirrupStrength = 3e8;
private IUpdateStrategy<IStirrup> updateStrategy; private IUpdateStrategy<IStirrup> updateStrategy;
public Dictionary<(Guid id, Type type), ISaveable> ReferenceDictionary { get; set; } public Dictionary<(Guid id, Type type), ISaveable> ReferenceDictionary { get; set; }
public IShiftTraceLogger TraceLogger { get; set; } public IShiftTraceLogger TraceLogger { get; set; }
@@ -36,12 +35,15 @@ namespace StructureHelperLogics.Models.BeamShears
private double GetStirrupDensity(IStirrupByRebar source) private double GetStirrupDensity(IStirrupByRebar source)
{ {
double area = Math.PI * source.Diameter * source.Diameter / 4d; double area = Math.PI * source.Diameter * source.Diameter / 4d;
TraceLogger?.AddMessage($"Area of rebar = {Math.PI} * ({source.Diameter})^2 / 4 = {area}, m^2"); TraceLogger?.AddMessage($"Area of rebar = {Math.PI} * ({source.Diameter})^2 / 4 = {area}(m^2)");
double strength = stirrupStrengthFactor * source.Material.GetStrength(LimitStates.ULS, CalcTerms.ShortTerm).Tensile; double materialStrength = source.Material.GetStrength(LimitStates.ULS, CalcTerms.ShortTerm).Tensile;
TraceLogger?.AddMessage($"Strength of rebar = {strength}, Pa"); TraceLogger?.AddMessage($"Stirrup material strength Rsw = {materialStrength}");
strength = Math.Min(strength, maxStirrupStrength); double stirrupStrength = stirrupStrengthFactor * materialStrength;
double density = strength * area * source.LegCount / source.Spacing; TraceLogger?.AddMessage($"Strength of rebar Rsw = {stirrupStrengthFactor} * {materialStrength} = {stirrupStrength}(Pa)");
TraceLogger?.AddMessage($"Density of stirrups = {strength} * {area} * {source.LegCount} / {source.Spacing} = {density}, N/m"); double minimizedStrength = Math.Min(stirrupStrength, maxStirrupStrength);
TraceLogger?.AddMessage($"Strength of rebar Rsw = Min({stirrupStrength}, {maxStirrupStrength})= {minimizedStrength}(Pa)");
double density = minimizedStrength * area * source.LegCount / source.Spacing;
TraceLogger?.AddMessage($"Density of stirrups = {minimizedStrength} * {area} * {source.LegCount} / {source.Spacing} = {density}(N/m)");
return density; return density;
} }
} }

View File

@@ -0,0 +1,78 @@
using StructureHelperCommon.Infrastructures.Exceptions;
using StructureHelperCommon.Models;
using StructureHelperCommon.Models.Calculators;
using StructureHelperLogics.Models.BeamShears.Logics;
namespace StructureHelperLogics.Models.BeamShears
{
internal class StirrupBySearchLogic : IBeamShearStrenghLogic
{
private ConcreteStrengthLogic concreteLogic;
private StirrupStrengthLogic stirrupLogic;
private ShiftTraceLogger? localTraceLogger { get; set; }
public StirrupBySearchLogic(IShiftTraceLogger? traceLogger)
{
TraceLogger = traceLogger;
}
public IShiftTraceLogger? TraceLogger { get; set; }
public IBeamShearSectionLogicInputData InputData { get; internal set; }
public ISectionEffectiveness SectionEffectiveness { get; internal set; }
public double GetShearStrength()
{
double parameter = GetParameter();
BeamShearSectionLogicInputData newInputData = GetNewInputData(parameter);
stirrupLogic = new(newInputData, localTraceLogger);
double stirrupStrength = stirrupLogic.GetShearStrength();
return stirrupStrength;
}
public double GetParameter()
{
var parameterCalculator = new FindParameterCalculator(TraceLogger);
parameterCalculator.InputData.Predicate = GetPredicate;
parameterCalculator.Accuracy.IterationAccuracy = 0.0001d;
parameterCalculator.Accuracy.MaxIterationCount = 1000;
parameterCalculator.Run();
if (parameterCalculator.Result.IsValid == false)
{
throw new StructureHelperException(ErrorStrings.DataIsInCorrect + $": predicate error");
}
var result = parameterCalculator.Result as FindParameterResult;
var parameter = result.Parameter;
return parameter;
}
private bool GetPredicate(double factor)
{
BeamShearSectionLogicInputData newInputData = GetNewInputData(factor);
concreteLogic = new(SectionEffectiveness, newInputData.InclinedSection, localTraceLogger);
stirrupLogic = new(newInputData, localTraceLogger);
double concreteStrength = concreteLogic.GetShearStrength();
double stirrupStrength = stirrupLogic.GetShearStrength();
return stirrupStrength > concreteStrength;
}
private BeamShearSectionLogicInputData GetNewInputData(double factor)
{
double sourceCrackLength = InputData.InclinedSection.EndCoord - InputData.InclinedSection.StartCoord;
double newCrackLength = sourceCrackLength * factor;
double newStartCoord = InputData.InclinedSection.EndCoord - newCrackLength;
InclinedSection newSection = new();
var updateStrategy = new InclinedSectionUpdateStrategy();
updateStrategy.Update(newSection, InputData.InclinedSection);
newSection.StartCoord = newStartCoord;
BeamShearSectionLogicInputData newInputData = new(Guid.Empty)
{
InclinedSection = newSection,
LimitState = InputData.LimitState,
CalcTerm = InputData.CalcTerm,
Stirrup = InputData.Stirrup,
ForceTuple = InputData.ForceTuple
};
return newInputData;
}
}
}

View File

@@ -1,12 +1,7 @@
using StructureHelperCommon.Infrastructures.Exceptions; using StructureHelperCommon.Infrastructures.Exceptions;
using StructureHelperCommon.Models; using StructureHelperCommon.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StructureHelperLogics.Models.BeamShears.Logics namespace StructureHelperLogics.Models.BeamShears
{ {
internal class StirrupStrengthLogic : IBeamShearStrenghLogic internal class StirrupStrengthLogic : IBeamShearStrenghLogic
{ {

View File

@@ -30,6 +30,11 @@ namespace StructureHelperLogics.Models.Materials
ProcessCollection(); ProcessCollection();
return traceLoggerEntries; return traceLoggerEntries;
} }
public void AddEntriesToTraceLogger(IShiftTraceLogger traceLogger)
{
var entries = GetTraceEntries();
entries.ForEach(x => traceLogger?.AddEntry(x));
}
private void ProcessCollection() private void ProcessCollection()
{ {
@@ -45,7 +50,6 @@ namespace StructureHelperLogics.Models.Materials
} }
traceLoggerEntries.Add(table); traceLoggerEntries.Add(table);
} }
private List<IShTableRow<ITraceLoggerEntry>> ProcessLibMaterial(ILibMaterial libMaterial) private List<IShTableRow<ITraceLoggerEntry>> ProcessLibMaterial(ILibMaterial libMaterial)
{ {
List<IShTableRow<ITraceLoggerEntry>> rows = new(); List<IShTableRow<ITraceLoggerEntry>> rows = new();
@@ -76,7 +80,6 @@ namespace StructureHelperLogics.Models.Materials
rows.Add(ndmRow); rows.Add(ndmRow);
return rows; return rows;
} }
private void Check() private void Check()
{ {
if (Collection is null) if (Collection is null)
@@ -84,7 +87,6 @@ namespace StructureHelperLogics.Models.Materials
throw new StructureHelperException(ErrorStrings.ParameterIsNull + ": Collection of primitives"); throw new StructureHelperException(ErrorStrings.ParameterIsNull + ": Collection of primitives");
} }
} }
private IShTableRow<ITraceLoggerEntry> GetHeader(IHeadMaterial headMaterial) private IShTableRow<ITraceLoggerEntry> GetHeader(IHeadMaterial headMaterial)
{ {
const CellRole cellRole = CellRole.Header; const CellRole cellRole = CellRole.Header;
@@ -263,10 +265,5 @@ namespace StructureHelperLogics.Models.Materials
return rows; return rows;
} }
public void AddEntriesToTraceLogger(IShiftTraceLogger traceLogger)
{
var entries = GetTraceEntries();
entries.ForEach(x => traceLogger?.AddEntry(x));
}
} }
} }

View File

@@ -5,6 +5,7 @@ namespace StructureHelperLogics.NdmCalculations.Analyses
{ {
public class ExportForcesResultToCSVLogic : ExportToCSVLogicBase public class ExportForcesResultToCSVLogic : ExportToCSVLogicBase
{ {
private const string errorString = "-error-";
IForcesResults results; IForcesResults results;
public ExportForcesResultToCSVLogic(IForcesResults results) public ExportForcesResultToCSVLogic(IForcesResults results)
@@ -45,14 +46,14 @@ namespace StructureHelperLogics.NdmCalculations.Analyses
} }
string[] newLine = string[] newLine =
{ {
item.DesignForceTuple.LimitState.ToString(), item.DesignForceTuple.LimitState.ToString() ?? errorString,
item.DesignForceTuple.CalcTerm.ToString(), item.DesignForceTuple.CalcTerm.ToString() ?? errorString,
tuple.Mx.ToString(), tuple.Mx.ToString() ?? errorString,
tuple.My.ToString(), tuple.My.ToString() ?? errorString,
tuple.Nz.ToString(), tuple.Nz.ToString() ?? errorString,
strainMatrix?.Kx.ToString(), strainMatrix?.Kx.ToString() ?? errorString,
strainMatrix?.Ky.ToString(), strainMatrix?.Ky.ToString() ?? errorString,
strainMatrix?.EpsZ.ToString() strainMatrix?.EpsZ.ToString() ?? errorString
}; };
output.AppendLine(string.Join(separator, newLine)); output.AppendLine(string.Join(separator, newLine));
} }

View File

@@ -10,7 +10,7 @@ using System.Threading.Tasks;
namespace StructureHelperLogics.NdmCalculations.Cracking namespace StructureHelperLogics.NdmCalculations.Cracking
{ {
public class CrackResult : IResult public class CrackResult : ICrackResult
{ {
public bool IsValid { get; set; } public bool IsValid { get; set; }
public string? Description { get; set; } public string? Description { get; set; }

View File

@@ -0,0 +1,9 @@
using StructureHelperCommon.Models.Calculators;
namespace StructureHelperLogics.NdmCalculations.Cracking
{
public interface ICrackResult : IResult
{
List<ITupleCrackResult> TupleResults { get; set; }
}
}

View File

@@ -0,0 +1,72 @@
using StructureHelperCommon.Models.Calculators;
using StructureHelperLogics.NdmCalculations.Analyses;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StructureHelperLogics.NdmCalculations.Cracking
{
public class ExportCrackResultToCSVLogic : ExportToCSVLogicBase
{
private const string errorString = "-error-";
private ICrackResult crackResult;
public ExportCrackResultToCSVLogic(ICrackResult crackResult)
{
this.crackResult = crackResult;
}
public override void ExportHeadings()
{
string[] headings =
{
"Action name",
"Long Nz",
"Long Mx",
"Long My",
"Long CrackWidth",
"Long UltimateCrackWidth",
"Long IsGood",
"Long Uf",
"Short Nz",
"Short Mx",
"Short My",
"Short CrackWidth",
"Short UltimateCrackWidth",
"Short IsGood",
"Short Uf",
};
output.AppendLine(string.Join(separator, headings));
}
public override void ExportBoby()
{
foreach (var item in crackResult.TupleResults)
{
//if (item.IsValid == true)
{
string[] newLine =
{
item?.InputData?.TupleName ?? errorString,
item?.InputData?.LongTermTuple?.Nz.ToString() ?? errorString,
item?.InputData?.LongTermTuple?.Mx.ToString() ?? errorString,
item?.InputData?.LongTermTuple?.My.ToString() ?? errorString,
item?.LongTermResult?.CrackWidth.ToString() ?? errorString,
item?.LongTermResult ?.UltimateCrackWidth.ToString() ?? errorString,
item?.LongTermResult ?.IsCrackLessThanUltimate.ToString() ?? errorString,
(item?.LongTermResult ?.CrackWidth / item?.LongTermResult?.UltimateCrackWidth).ToString() ?? errorString,
item?.InputData?.ShortTermTuple?.Nz.ToString() ?? errorString,
item?.InputData?.ShortTermTuple?.Mx.ToString() ?? errorString,
item ?.InputData?.ShortTermTuple?.My.ToString() ?? errorString,
item?.ShortTermResult?.CrackWidth.ToString() ?? errorString,
item?.ShortTermResult?.UltimateCrackWidth.ToString() ?? errorString,
item?.ShortTermResult?.IsCrackLessThanUltimate.ToString() ?? errorString,
(item?.ShortTermResult?.CrackWidth / item?.ShortTermResult?.UltimateCrackWidth).ToString() ?? errorString,
};
output.AppendLine(string.Join(separator, newLine));
}
}
}
}
}

View File

@@ -16,8 +16,4 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Models\Materials\DTOs\" />
</ItemGroup>
</Project> </Project>

View File

@@ -3,135 +3,113 @@ using NUnit.Framework;
using StructureHelperCommon.Infrastructures.Exceptions; using StructureHelperCommon.Infrastructures.Exceptions;
using StructureHelperCommon.Infrastructures.Interfaces; using StructureHelperCommon.Infrastructures.Interfaces;
using StructureHelperCommon.Models; using StructureHelperCommon.Models;
using StructureHelperLogics.Models.BeamShears.Logics;
using StructureHelperLogics.Models.BeamShears; using StructureHelperLogics.Models.BeamShears;
using StructureHelperLogics.Models.BeamShears.Logics;
using System;
namespace StructureHelperTests.UnitTests.BeamShearTests namespace StructureHelperTests.UnitTests.BeamShearTests
{ {
[TestFixture] [TestFixture]
public class GetLongitudinalForceFactorLogicTests public class GetLongitudinalForceFactorLogicTests
{ {
private Mock<IInclinedSection> _mockSection; [Test]
private Mock<ICheckEntityLogic<IInclinedSection>> _mockCheckLogic; public void GetFactor_When_LongitudinalForceIsZero_ReturnsOne()
private Mock<IShiftTraceLogger> _mockLogger;
private GetLongitudinalForceFactorLogic _logic;
[SetUp]
public void SetUp()
{ {
_mockSection = new Mock<IInclinedSection>(); var traceLogger = new Mock<IShiftTraceLogger>();
_mockCheckLogic = new Mock<ICheckEntityLogic<IInclinedSection>>(); var inclinedSection = new Mock<IInclinedSection>();
_mockLogger = new Mock<IShiftTraceLogger>(); var mockCheckLogic = new Mock<ICheckEntityLogic<IInclinedSection>>();
mockCheckLogic.Setup(x => x.Check()).Returns(true);
List<ITraceLoggerEntry> traceLoggerEntries = new();
traceLogger.Setup(x => x.TraceLoggerEntries).Returns(traceLoggerEntries);
_logic = new GetLongitudinalForceFactorLogic(_mockLogger.Object) var mockReducedAreaLogic = new Mock<IGetReducedAreaLogic>();
var logic = new GetLongitudinalForceFactorLogic(mockCheckLogic.Object, mockReducedAreaLogic.Object, traceLogger.Object)
{ {
InclinedSection = _mockSection.Object, InclinedSection = inclinedSection.Object,
LongitudinalForce = 0 LongitudinalForce = 0
}; };
// Inject mock check logic var result = logic.GetFactor();
typeof(GetLongitudinalForceFactorLogic)
.GetField("checkInclinedSectionLogic", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
?.SetValue(_logic, _mockCheckLogic.Object);
}
[Test]
public void GetFactor_Returns1_WhenLongitudinalForceIsZero()
{
// Arrange
_mockCheckLogic.Setup(c => c.Check()).Returns(true);
// Act
var result = _logic.GetFactor();
// Assert
Assert.That(result, Is.EqualTo(1)); Assert.That(result, Is.EqualTo(1));
} }
[Test] [Test]
public void GetFactor_ComputesCorrectly_ForTension() public void GetFactor_When_CheckFails_ThrowsStructureHelperException()
{ {
// Arrange var traceLogger = new Mock<IShiftTraceLogger>();
_logic.LongitudinalForce = 100000; // tension var inclinedSection = new Mock<IInclinedSection>();
_mockSection.Setup(s => s.WebWidth).Returns(0.3); var mockCheckLogic = new Mock<ICheckEntityLogic<IInclinedSection>>();
_mockSection.Setup(s => s.FullDepth).Returns(0.5); List<ITraceLoggerEntry> traceLoggerEntries = new();
_mockSection.Setup(s => s.ConcreteTensionStrength).Returns(2000000); traceLogger.Setup(x => x.TraceLoggerEntries).Returns(traceLoggerEntries);
_mockCheckLogic.Setup(c => c.Check()).Returns(true);
double area = 0.3 * 0.5; mockCheckLogic.Setup(x => x.Check()).Returns(false);
double stress = 100000 / area; mockCheckLogic.Setup(x => x.CheckResult).Returns("Check failed");
double ratio = stress / 2000000;
double expected = Math.Max(1 - 0.5 * ratio, 0);
// Act var mockReducedAreaLogic = new Mock<IGetReducedAreaLogic>();
var result = _logic.GetFactor(); var logic = new GetLongitudinalForceFactorLogic(mockCheckLogic.Object, mockReducedAreaLogic.Object, traceLogger.Object)
{
InclinedSection = inclinedSection.Object,
LongitudinalForce = 1000
};
// Assert Assert.That(() => logic.GetFactor(), Throws.TypeOf<StructureHelperException>());
Assert.That(result, Is.EqualTo(expected).Within(1e-6)); }
[TestCase(-1, 1.0000000333333334d)] //1N
[TestCase(-1000000, 1.0333333333333334d)] //1MN
[TestCase(-10000000, 1.25d)] //10MN
[TestCase(-20000000, 0.83333333333333348d)] //20MN
[TestCase(-100000000, 0)] //100MN
public void GetFactor_When_Compression_ReturnsExpectedResult(double force, double expectedFactor)
{
var traceLogger = new Mock<IShiftTraceLogger>();
var inclinedSection = new Mock<IInclinedSection>();
var mockCheckLogic = new Mock<ICheckEntityLogic<IInclinedSection>>();
var mockReducedAreaLogic = new Mock<IGetReducedAreaLogic>();
List<ITraceLoggerEntry> traceLoggerEntries = new();
traceLogger.Setup(x => x.TraceLoggerEntries).Returns(traceLoggerEntries);
mockCheckLogic.Setup(x => x.Check()).Returns(true);
mockReducedAreaLogic.Setup(x => x.GetArea()).Returns(1.0);
inclinedSection.Setup(x => x.ConcreteCompressionStrength).Returns(30e6);
var logic = new GetLongitudinalForceFactorLogic(mockCheckLogic.Object, mockReducedAreaLogic.Object, traceLogger.Object)
{
InclinedSection = inclinedSection.Object,
LongitudinalForce = force
};
var result = logic.GetFactor();
Assert.That(result, Is.EqualTo(expectedFactor).Within(1e-6));
} }
[Test] [Test]
public void GetFactor_ComputesCorrectly_ForCompression_WithinFirstLimit() public void GetFactor_When_Tension_ReturnsExpectedResult()
{ {
// Arrange var traceLogger = new Mock<IShiftTraceLogger>();
_logic.LongitudinalForce = -10000; // compression var inclinedSection = new Mock<IInclinedSection>();
_mockSection.Setup(s => s.WebWidth).Returns(0.3); var mockCheckLogic = new Mock<ICheckEntityLogic<IInclinedSection>>();
_mockSection.Setup(s => s.FullDepth).Returns(0.5); var mockReducedAreaLogic = new Mock<IGetReducedAreaLogic>();
_mockSection.Setup(s => s.ConcreteCompressionStrength).Returns(25000000); List<ITraceLoggerEntry> traceLoggerEntries = new();
_mockCheckLogic.Setup(c => c.Check()).Returns(true); traceLogger.Setup(x => x.TraceLoggerEntries).Returns(traceLoggerEntries);
double area = 0.3 * 0.5; mockCheckLogic.Setup(x => x.Check()).Returns(true);
double stress = 10000 / area; mockReducedAreaLogic.Setup(x => x.GetArea()).Returns(1.0);
double ratio = stress / 25000000;
double expected = 1 + ratio;
// Act inclinedSection.Setup(x => x.ConcreteTensionStrength).Returns(3e6);
var result = _logic.GetFactor();
// Assert var logic = new GetLongitudinalForceFactorLogic(mockCheckLogic.Object, mockReducedAreaLogic.Object, traceLogger.Object)
Assert.That(result, Is.EqualTo(expected).Within(1e-6));
}
[TestCase(-11250000 / 3.99)]
[TestCase(-11250000 / 3)]
[TestCase(-11250000)]
public void GetFactor_ComputesCorrectly_ForCompression_HighRatio(double force)
{ {
// Arrange InclinedSection = inclinedSection.Object,
_logic.LongitudinalForce = force; // compression LongitudinalForce = 1000000 // +1MN
_mockSection.Setup(s => s.WebWidth).Returns(0.3); };
_mockSection.Setup(s => s.FullDepth).Returns(0.5);
_mockSection.Setup(s => s.ConcreteCompressionStrength).Returns(25000000);
_mockCheckLogic.Setup(c => c.Check()).Returns(true);
double area = 0.3 * 0.5; var result = logic.GetFactor();
double stress = - force / area;
double ratio = stress / 25000000;
Assert.That(ratio, Is.GreaterThan(0.75)); // high compression branch Assert.That(result, Is.GreaterThanOrEqualTo(0));
double expected = Math.Max(5 * (1 - ratio), 0);
// Act
var result = _logic.GetFactor();
// Assert
Assert.That(result, Is.EqualTo(expected).Within(1e-6));
}
[Test]
public void GetFactor_Throws_WhenCheckFails()
{
// Arrange
_mockCheckLogic.Setup(c => c.Check()).Returns(false);
_mockCheckLogic.Setup(c => c.CheckResult).Returns("Invalid section");
// Act & Assert
var ex = Assert.Throws<StructureHelperException>(() => _logic.GetFactor());
Assert.That(ex.Message, Does.Contain("Invalid section"));
} }
} }
} }

View File

@@ -0,0 +1,56 @@
using LoaderCalculator.Data.Materials;
using Moq;
using NUnit.Framework;
using StructureHelperCommon.Infrastructures.Enums;
using StructureHelperCommon.Models.Materials;
using StructureHelperLogics.Models.BeamShears;
using StructureHelperLogics.Models.Materials;
using System;
namespace StructureHelperTests.UnitTests.BeamShearTests
{
[TestFixture]
public class GetReducedAreaLogicSP63_2018_rev3Tests
{
[TestCase(-500, 0.3, 0.5, 0.001, 0.16999999999999998d)]
[TestCase(-500, 0.3, 0.5, 0.002, 0.19d)]
[TestCase(1000, 0.3, 0.5, 0.001, 0.16666666666666666d)]
[TestCase(1000, 0.3, 0.5, 0.002, 0.18333333333333335d)]
public void GetArea_ReturnsCorrectResult(double force, double width, double depth, double reinforcementArea, double expectedArea)
{
// Arrange
var mockConcreteMaterial = new Mock<IConcreteLibMaterial>();
mockConcreteMaterial.Setup(m => m.GetLoaderMaterial(It.IsAny<LimitStates>(), It.IsAny<CalcTerms>()))
.Returns(new Material { InitModulus = 3e10 });
mockConcreteMaterial.Setup(m => m.GetStrength(It.IsAny<LimitStates>(), It.IsAny<CalcTerms>()))
.Returns((20e6, 1.2e6));
var mockReinforcementMaterial = new Mock<IReinforcementLibMaterial>();
mockReinforcementMaterial.Setup(m => m.GetLoaderMaterial(It.IsAny<LimitStates>(), It.IsAny<CalcTerms>()))
.Returns(new Material { InitModulus = 2e11 });
mockReinforcementMaterial.Setup(m => m.GetStrength(It.IsAny<LimitStates>(), It.IsAny<CalcTerms>()))
.Returns((200e6, 200e6));
var mockSection = new Mock<IBeamShearSection>();
mockSection.Setup(s => s.ConcreteMaterial).Returns(mockConcreteMaterial.Object);
mockSection.Setup(s => s.ReinforcementMaterial).Returns(mockReinforcementMaterial.Object);
mockSection.Setup(s => s.ReinforcementArea).Returns(reinforcementArea);
var mockInclSection = new Mock<IInclinedSection>();
mockInclSection.Setup(s => s.WebWidth).Returns(width);
mockInclSection.Setup(s => s.FullDepth).Returns(depth);
mockInclSection.Setup(s => s.BeamShearSection).Returns(mockSection.Object);
mockInclSection.Setup(s => s.LimitState).Returns(LimitStates.ULS);
mockInclSection.Setup(s => s.CalcTerm).Returns(CalcTerms.ShortTerm);
var logic = new GetReducedAreaLogicSP63_2018_rev3(force, mockInclSection.Object, null);
// Act
var result = logic.GetArea();
// Assert
Assert.That(result, Is.EqualTo(expectedArea).Within(1e-6));
}
}
}

View File

@@ -49,7 +49,7 @@ namespace StructureHelperTests.UnitTests.BeamShearTests
// Assert // Assert
_mockUpdateStrategy.Verify(u => u.Update(It.IsAny<IStirrupByDensity>(), stirrupRebar.Object), Times.Once); _mockUpdateStrategy.Verify(u => u.Update(It.IsAny<IStirrupByDensity>(), stirrupRebar.Object), Times.Once);
Assert.That(result.StirrupDensity, Is.EqualTo(837758.04095727834d).Within(0.00001)); Assert.That(result.StirrupDensity, Is.EqualTo(670206.43276582274d).Within(0.00001));
//_mockTraceLogger.Verify(t => t.AddMessage(It.IsAny<string>(), It.IsAny<TraceLogStatuses>()), Times.AtLeastOnce); //_mockTraceLogger.Verify(t => t.AddMessage(It.IsAny<string>(), It.IsAny<TraceLogStatuses>()), Times.AtLeastOnce);
} }
} }