Загрузка данных
using NUnit.Framework;
using lab3.transport;
namespace lab3.tests
{
[TestFixture]
public class TaxiTests
{
// 6. Такси: выручка = цена/км × км × пассажиры
[Test]
public void Taxi_CalculatesRevenueByDistanceAndPassengers()
{
var taxi = new Taxi(costPerKm: 20, totalKm: 15);
for (int i = 0; i < 4; i++) taxi.AddPassenger(false);
// 20 × 15 × 4 = 1200
Assert.That(taxi.CalculateRevenue(), Is.EqualTo(1200.0));
}
// 7. Такси игнорирует льготный флаг (у такси нет льготных билетов)
[Test]
public void Taxi_BenefitFlag_DoesNotAffectRevenue()
{
var taxi = new Taxi(costPerKm: 20, totalKm: 10);
taxi.AddPassenger(false); // обычный
taxi.AddPassenger(true); // «льготник» — но формула одна
// 20 × 10 × 2 = 400, независимо от флагов
Assert.That(taxi.CalculateRevenue(), Is.EqualTo(400.0));
}
}
}
using NUnit.Framework;
using lab3.transport.public_transport;
namespace lab3.tests
{
[TestFixture]
public class FareTransportTests
{
// 1. Автобус: смешанные пассажиры — формула выручки
[Test]
public void Bus_WithMixedPassengers_CalculatesRevenueCorrectly()
{
// Arrange
var bus = new Bus(generalTicketCost: 30, benefitTicketCost: 15, routeNumber: "12");
// Act
for (int i = 0; i < 10; i++) bus.AddPassenger(false);
for (int i = 0; i < 3; i++) bus.AddPassenger(true);
// Assert
// (10 × 30) + (3 × 15) = 300 + 45 = 345
Assert.That(bus.CalculateRevenue(), Is.EqualTo(345.0));
}
// 2. Автобус без пассажиров — выручка равна нулю
[Test]
public void Bus_WithoutPassengers_ReturnsZeroRevenue()
{
var bus = new Bus(30, 15, "12");
Assert.That(bus.CalculateRevenue(), Is.EqualTo(0.0));
}
// 3. Автобус только со льготниками — используется льготный тариф
[Test]
public void Bus_OnlyBenefitPassengers_UsesBenefitTicketCost()
{
var bus = new Bus(generalTicketCost: 30, benefitTicketCost: 15, routeNumber: "12");
for (int i = 0; i < 5; i++) bus.AddPassenger(true);
// 5 × 15 = 75
Assert.That(bus.CalculateRevenue(), Is.EqualTo(75.0));
}
// 4. Счётчики пассажиров: обычные и льготники разделены
[Test]
public void PassengerCounters_TrackRegularAndBenefitSeparately()
{
var tram = new Tram(25, 12, "4");
for (int i = 0; i < 7; i++) tram.AddPassenger(false);
for (int i = 0; i < 3; i++) tram.AddPassenger(true);
Assert.Multiple(() =>
{
Assert.That(tram.PassengerCount, Is.EqualTo(10));
Assert.That(tram.BenefitPassengerCount, Is.EqualTo(3));
});
}
// 5. Параметризованный тест для разных видов «билетного» транспорта:
// у всех формула одинаковая, отличаются лишь цены
[TestCase(30, 15, 10, 3, 345.0)] // Bus
[TestCase(25, 12, 8, 2, 224.0)] // Tram
[TestCase(28, 14, 6, 1, 182.0)] // Trolleybus
[TestCase(150, 75, 50, 10, 8250.0)] // Train
public void FareTransport_RevenueFormula_IsUniform(
int general, int benefit, int regularCount, int benefitCount, double expected)
{
var bus = new Bus(general, benefit, "test");
for (int i = 0; i < regularCount; i++) bus.AddPassenger(false);
for (int i = 0; i < benefitCount; i++) bus.AddPassenger(true);
Assert.That(bus.CalculateRevenue(), Is.EqualTo(expected));
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.10.1" />
<PackageReference Include="NUnit" Version="5.0.0" />
<PackageReference Include="NUnit3TestAdapter" Version="6.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\lab3\lab3.csproj" />
</ItemGroup>
</Project>
using NUnit.Framework;
using lab3.transport.public_transport;
namespace lab3.tests
{
[TestFixture]
public class MinibusTests
{
// 8. Маршрутка: не пускает пассажиров сверх вместимости
[Test]
public void Minibus_DoesNotExceedCapacity()
{
var minibus = new Minibus(
generalTicketCost: 40,
benefitTicketCost: 20,
routeNumber: "45",
capacity: 3);
for (int i = 0; i < 5; i++) minibus.AddPassenger(false);
Assert.That(minibus.PassengerCount, Is.EqualTo(3));
}
// 9. Маршрутка: IsFull становится true при достижении вместимости
[Test]
public void Minibus_IsFull_ReturnsTrueWhenAtCapacity()
{
var minibus = new Minibus(40, 20, "45", capacity: 2);
Assert.That(minibus.IsFull, Is.False);
minibus.AddPassenger(false);
minibus.AddPassenger(true);
Assert.Multiple(() =>
{
Assert.That(minibus.IsFull, Is.True);
Assert.That(minibus.PassengerCount, Is.EqualTo(2));
Assert.That(minibus.BenefitPassengerCount, Is.EqualTo(1));
});
}
}
}
namespace lab3.transport
{
public abstract class FareTransport : PassengerTransport
{
protected readonly int _generalTicketCost;
protected readonly int _benefitTicketCost;
protected FareTransport(int generalTicketCost, int benefitTicketCost)
{
_generalTicketCost = generalTicketCost;
_benefitTicketCost = benefitTicketCost;
}
public override double CalculateRevenue()
{
return (PassengerCount - BenefitPassengerCount) * _generalTicketCost
+ BenefitPassengerCount * _benefitTicketCost;
}
}
}
namespace lab3.transport
{
public abstract class PassengerTransport : Transport, IPassengerCarrier
{
public int PassengerCount { get; protected set; }
public int BenefitPassengerCount { get; protected set; }
public virtual void AddPassenger(bool hasBenefit)
{
PassengerCount += 1;
if (hasBenefit)
BenefitPassengerCount += 1;
}
}
}
namespace lab3.transport
{
public sealed class Taxi : PassengerTransport
{
public int CostPerKm { get; }
private readonly int _totalKm;
public Taxi(int costPerKm, int totalKm)
{
CostPerKm = costPerKm;
_totalKm = totalKm;
}
public override double CalculateRevenue()
{
return CostPerKm * _totalKm * PassengerCount;
}
}
}
namespace lab3.transport.public_transport
{
public sealed class Bus : FareTransport, IRouteBased
{
public string RouteNumber { get; }
public Bus(int generalTicketCost, int benefitTicketCost, string routeNumber)
: base(generalTicketCost, benefitTicketCost)
{
RouteNumber = routeNumber;
}
}
}
namespace lab3.transport.public_transport
{
public sealed class Minibus : FareTransport, IRouteBased, ICapacityLimited
{
public string RouteNumber { get; }
public int Capacity { get; }
public bool IsFull => PassengerCount >= Capacity;
public Minibus(int generalTicketCost, int benefitTicketCost,
string routeNumber, int capacity)
: base(generalTicketCost, benefitTicketCost)
{
RouteNumber = routeNumber;
Capacity = capacity;
}
public override void AddPassenger(bool hasBenefit)
{
if (IsFull)
return; // переопределение базового поведения
base.AddPassenger(hasBenefit);
}
}
}
namespace lab3.transport.public_transport
{
public sealed class Train : FareTransport, IRouteBased
{
public string RouteNumber { get; }
public Train(int generalTicketCost, int benefitTicketCost, string routeNumber)
: base(generalTicketCost, benefitTicketCost)
{
RouteNumber = routeNumber;
}
}
}
namespace lab3.transport.public_transport
{
public sealed class Tram : FareTransport, IRouteBased
{
public string RouteNumber { get; }
public Tram(int generalTicketCost, int benefitTicketCost, string routeNumber)
: base(generalTicketCost, benefitTicketCost)
{
RouteNumber = routeNumber;
}
}
}
namespace lab3.transport.public_transport
{
public sealed class Trolleybus : FareTransport, IRouteBased
{
public string RouteNumber { get; }
public Trolleybus(int generalTicketCost, int benefitTicketCost, string routeNumber)
: base(generalTicketCost, benefitTicketCost)
{
RouteNumber = routeNumber;
}
}
}
namespace lab3
{
public interface ICapacityLimited
{
int Capacity { get; }
bool IsFull { get; }
}
}
namespace lab3
{
public interface IPassengerCarrier
{
int PassengerCount { get; }
int BenefitPassengerCount { get; }
void AddPassenger(bool hasBenefit);
}
}
namespace lab3
{
public interface IRevenueCalculatable
{
double CalculateRevenue();
}
}
namespace lab3
{
public interface IRouteBased
{
string RouteNumber { get; }
}
}
using lab3.transport;
using lab3.transport.public_transport;
namespace lab3
{
internal class Program
{
static void Main()
{
Console.WriteLine("=== Демонстрация работы транспорта ===\n");
// --- Такси: тариф за км, льгот нет ---
var taxi = new Taxi(costPerKm: 25, totalKm: 40);
taxi.AddPassenger(false);
taxi.AddPassenger(false);
taxi.AddPassenger(true);
Console.WriteLine($"Такси: пассажиров = {taxi.PassengerCount}, " +
$"из них льготных = {taxi.BenefitPassengerCount}, " +
$"выручка = {taxi.CalculateRevenue():F2}");
// --- Автобус: фиксированная стоимость билета ---
var bus = new Bus(generalTicketCost: 50, benefitTicketCost: 25, routeNumber: "12A");
bus.AddPassenger(false);
bus.AddPassenger(true);
bus.AddPassenger(false);
bus.AddPassenger(true);
Console.WriteLine($"Автобус (маршрут {bus.RouteNumber}): " +
$"пассажиров = {bus.PassengerCount}, " +
$"льготных = {bus.BenefitPassengerCount}, " +
$"выручка = {bus.CalculateRevenue():F2}");
// --- Маршрутка: ограниченная вместимость ---
var minibus = new Minibus(generalTicketCost: 40, benefitTicketCost: 20,
routeNumber: "8", capacity: 3);
for (int i = 0; i < 5; i++)
minibus.AddPassenger(i % 2 == 0); // 5 попыток, но влезет только 3
Console.WriteLine($"Маршрутка (маршрут {minibus.RouteNumber}): " +
$"вместимость = {minibus.Capacity}, " +
$"пассажиров = {minibus.PassengerCount}, " +
$"заполнена = {minibus.IsFull}, " +
$"выручка = {minibus.CalculateRevenue():F2}");
// --- Трамвай ---
var tram = new Tram(generalTicketCost: 30, benefitTicketCost: 15, routeNumber: "5");
tram.AddPassenger(false);
tram.AddPassenger(true);
tram.AddPassenger(true);
Console.WriteLine($"Трамвай (маршрут {tram.RouteNumber}): " +
$"пассажиров = {tram.PassengerCount}, " +
$"выручка = {tram.CalculateRevenue():F2}");
// --- Троллейбус ---
var trolleybus = new Trolleybus(generalTicketCost: 35, benefitTicketCost: 17,
routeNumber: "7");
trolleybus.AddPassenger(false);
trolleybus.AddPassenger(false);
Console.WriteLine($"Троллейбус (маршрут {trolleybus.RouteNumber}): " +
$"выручка = {trolleybus.CalculateRevenue():F2}");
// --- Поезд ---
var train = new Train(generalTicketCost: 100, benefitTicketCost: 50,
routeNumber: "Электричка 6001");
for (int i = 0; i < 10; i++) train.AddPassenger(false);
train.AddPassenger(true);
train.AddPassenger(true);
Console.WriteLine($"Поезд (маршрут {train.RouteNumber}): " +
$"пассажиров = {train.PassengerCount}, " +
$"выручка = {train.CalculateRevenue():F2}");
// --- Полиморфная обработка списка через базовый класс Transport ---
Console.WriteLine("\n=== Полиморфная обработка списка транспорта ===");
var transports = new List<Transport>
{
taxi, bus, minibus, tram, trolleybus, train
};
double totalRevenue = 0;
foreach (var t in transports)
{
double revenue = t.CalculateRevenue();
totalRevenue += revenue;
string info = t is IRouteBased rb ? $"маршрут {rb.RouteNumber}" : "без маршрута";
Console.WriteLine($"{t.GetType().Name,-12} {info,-25} выручка = {revenue,10:F2}");
}
Console.WriteLine($"\nОбщая выручка: {totalRevenue:F2}");
// --- Работа с интерфейсами через приведение типов ---
Console.WriteLine("\n=== ICapacityLimited ===");
foreach (var t in transports)
if (t is ICapacityLimited cl)
Console.WriteLine($" {t.GetType().Name}: вместимость = {cl.Capacity}, " +
$"заполнен = {cl.IsFull}");
Console.WriteLine("\n=== IRouteBased ===");
foreach (var t in transports)
if (t is IRouteBased r)
Console.WriteLine($" {t.GetType().Name}: маршрут = {r.RouteNumber}");
Console.WriteLine("\n=== IPassengerCarrier ===");
foreach (var t in transports)
if (t is IPassengerCarrier pc)
Console.WriteLine($" {t.GetType().Name}: пассажиров = {pc.PassengerCount}, " +
$"льготных = {pc.BenefitPassengerCount}");
// --- Сортировка по выручке (используем IRevenueCalculatable полиморфно) ---
Console.WriteLine("\n=== Транспорт, отсортированный по выручке (по убыванию) ===");
var sorted = new List<Transport>(transports);
sorted.Sort((a, b) => b.CalculateRevenue().CompareTo(a.CalculateRevenue()));
foreach (var t in sorted)
Console.WriteLine($" {t.GetType().Name,-12} = {t.CalculateRevenue(),10:F2}");
}
}
}
namespace lab3
{
public abstract class Transport : IRevenueCalculatable
{
public abstract double CalculateRevenue();
}
}