From fcd703a0d7c5e78aec5878b42cf24c86ca843ea5 Mon Sep 17 00:00:00 2001 From: Kai Nagel Date: Mon, 23 Oct 2023 08:16:36 +0200 Subject: [PATCH 1/4] add traditional constructor injection to compare with guice injection --- .../guicewithoutmatsim/PartOne.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/matsim/codeexamples/guicewithoutmatsim/PartOne.java b/src/main/java/org/matsim/codeexamples/guicewithoutmatsim/PartOne.java index a5e81c23..e86364e5 100644 --- a/src/main/java/org/matsim/codeexamples/guicewithoutmatsim/PartOne.java +++ b/src/main/java/org/matsim/codeexamples/guicewithoutmatsim/PartOne.java @@ -13,14 +13,20 @@ class PartOne{ private static final Logger log = LogManager.getLogger( PartOne.class ) ; public static void main(String[] args){ + +// // traditional constructor injection: +// Helper helper = new MyHelper1(); +// Simulation sim = new MySimulation1( helper ); + + // guice injection: Injector injector = Guice.createInjector( new AbstractModule(){ @Override protected void configure(){ bind(Simulation.class).to( MySimulation1.class ) ; bind( Helper.class ).to( MyHelper1.class ) ; -// MapBinder.newMapBinder( this, "car", ) } } ); Simulation sim = injector.getInstance(Simulation.class); + sim.run() ; } @@ -33,15 +39,20 @@ interface Helper { } static class MySimulation1 implements Simulation { - // arguments that would normally be in the constructor can now be obtained via @Inject ! - @Inject Helper helper ; + private final Helper helper; + @Inject MySimulation1( Helper helper ) { + this.helper = helper; + } @Override public void run() { log.info( "called MySimulation1 run method") ; helper.getAccessToSomething() ; } } static class MySimulation2 implements Simulation { - @Inject Helper helper ; + private final Helper helper; + @Inject MySimulation2( Helper helper ) { + this.helper = helper; + } @Override public void run() { log.info( "called MySimulation2 run method") ; helper.getAccessToSomething() ; From 11241582b5d52d84752cef5605c26c96b5d67f83 Mon Sep 17 00:00:00 2001 From: Kai Nagel Date: Mon, 23 Oct 2023 08:33:35 +0200 Subject: [PATCH 2/4] add ev own consumption model example --- .../RunEvExampleWithOwnConsumptionModel.java | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 src/main/java/org/matsim/codeexamples/extensions/electricVehicles/RunEvExampleWithOwnConsumptionModel.java diff --git a/src/main/java/org/matsim/codeexamples/extensions/electricVehicles/RunEvExampleWithOwnConsumptionModel.java b/src/main/java/org/matsim/codeexamples/extensions/electricVehicles/RunEvExampleWithOwnConsumptionModel.java new file mode 100644 index 00000000..41f71e73 --- /dev/null +++ b/src/main/java/org/matsim/codeexamples/extensions/electricVehicles/RunEvExampleWithOwnConsumptionModel.java @@ -0,0 +1,134 @@ +/* *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2016 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** */ + +package org.matsim.codeexamples.extensions.electricVehicles; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.api.core.v01.network.Link; +import org.matsim.contrib.ev.EvConfigGroup; +import org.matsim.contrib.ev.EvModule; +import org.matsim.contrib.ev.discharging.AuxEnergyConsumption; +import org.matsim.contrib.ev.discharging.DriveEnergyConsumption; +import org.matsim.contrib.ev.discharging.LTHDriveEnergyConsumption; +import org.matsim.contrib.ev.fleet.ElectricVehicle; +import org.matsim.contrib.ev.infrastructure.LTHConsumptionModelReader; +import org.matsim.contrib.ev.routing.EvNetworkRoutingProvider; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigGroup; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controler; +import org.matsim.core.controler.OutputDirectoryHierarchy; +import org.matsim.core.scenario.ScenarioUtils; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; + +/** + * Runs a sample EV run using a vehicle consumption model designed at LTH in Lund which takes the speed and the slope of a link into account. + * Link slopes may be added using a double array on the network. + * The consumption maps are based on Domingues, Gabriel. / Modeling, Optimization and Analysis of Electromobility Systems. Lund : Department of Biomedical Engineering, Lund university, 2018. 169 p., PhD thesis + */ +public class RunEvExampleWithOwnConsumptionModel{ + static final String DEFAULT_CONFIG_FILE = "test/input/org/matsim/contrib/ev/example/RunEvExample/config.xml"; + private static final Logger log = LogManager.getLogger( RunEvExampleWithOwnConsumptionModel.class ); + + public static void main(String[] args) throws IOException { + if (args.length > 0) { + log.info("Starting simulation run with the following arguments:"); + log.info("args=" + Arrays.toString( args ) ); + } else { + File localConfigFile = new File(DEFAULT_CONFIG_FILE); + if (localConfigFile.exists()) { + log.info("Starting simulation run with the local example config file"); + args = new String[]{ DEFAULT_CONFIG_FILE }; + } else { + log.info("Starting simulation run with the example config file from GitHub repository"); + args = new String[]{"https://raw.githubusercontent.com/matsim-org/matsim/master/contribs/ev/" + + DEFAULT_CONFIG_FILE }; + } + } + new RunEvExampleWithOwnConsumptionModel().run(args ); + } + + public void run( String[] args ) { + Config config = ConfigUtils.loadConfig(args, new EvConfigGroup()); + config.controler().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + + // === + + Scenario scenario = ScenarioUtils.loadScenario(config); + + // === + + Controler controler = new Controler(scenario); + { + DriveEnergyConsumption.Factory driveEnergyConsumptionFactory = new DriveEnergyConsumption.Factory(){ + @Override public DriveEnergyConsumption create( ElectricVehicle electricVehicle ){ + DriveEnergyConsumption.Factory factory = new LTHConsumptionModelReader(null).readURL( ConfigGroup.getInputFileURL( config.getContext(), "MidCarMap.csv" ) ); + DriveEnergyConsumption delegate = factory.create( electricVehicle ); + + DriveEnergyConsumption consumption = new DriveEnergyConsumption(){ + @Override public double calcEnergyConsumption( Link link, double travelTime, double linkEnterTime ){ + + // discharge because the link must be driven: + double delta = delegate.calcEnergyConsumption( link, travelTime, linkEnterTime ); + + double desiredSocAtEndOfLink = (double) electricVehicle.getVehicleSpecification().getMatsimVehicle().getAttributes().getAttribute( "whatever" ); + + return electricVehicle.getBattery().getSoc() - desiredSocAtEndOfLink; + // * above will often be negative; this is the purpose: discharging is negative i.e. we are + // charging on the link. ((This is why I am in general against hiding the sign in the method + // name. kai)) + + // * above is in SOC space, needs to be translated into kWh space + + // * need to make sure that the above charging is physically possible + + // * need to make sure that we are not discharging beyond what is needed to drive the link + + } + }; + return consumption; + } + }; + + controler.addOverridingModule( new EvModule() ); + controler.addOverridingModule( new AbstractModule(){ + @Override + public void install(){ + bind( DriveEnergyConsumption.Factory.class ).toInstance( driveEnergyConsumptionFactory ); + bind( AuxEnergyConsumption.Factory.class ).toInstance( + electricVehicle -> ( beginTime, duration, linkId ) -> 0 ); //a dummy factory, as aux consumption is part of the drive consumption in the model + + addRoutingModuleBinding( TransportMode.car ).toProvider( new EvNetworkRoutingProvider( TransportMode.car ) ); + // a router that inserts charging activities when the battery is run empty. there may be some other way to insert + // charging activities, based on the situation. kai, dec'22 + } + } ); + } + + + controler.run(); + } +} From 70f037ba4e85c1a61e25a3d9ad9d311699cbc181 Mon Sep 17 00:00:00 2001 From: Kai Nagel Date: Thu, 16 Nov 2023 07:57:29 +0100 Subject: [PATCH 3/4] delete guice example that had nothing to do with matsim. have better examples now --- .../guicewithoutmatsim/GuiceTester.java | 58 ------------------- 1 file changed, 58 deletions(-) delete mode 100644 src/main/java/org/matsim/codeexamples/guicewithoutmatsim/GuiceTester.java diff --git a/src/main/java/org/matsim/codeexamples/guicewithoutmatsim/GuiceTester.java b/src/main/java/org/matsim/codeexamples/guicewithoutmatsim/GuiceTester.java deleted file mode 100644 index 4248af9e..00000000 --- a/src/main/java/org/matsim/codeexamples/guicewithoutmatsim/GuiceTester.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.matsim.codeexamples.guicewithoutmatsim; - -import com.google.inject.AbstractModule; -import com.google.inject.Guice; -import com.google.inject.ImplementedBy; -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.google.inject.name.Named; -import com.google.inject.name.Names; - -public class GuiceTester { - public static void main(String[] args) { - Injector injector = Guice.createInjector(new TextEditorModule()); - TextEditor editor = injector.getInstance(TextEditor.class); - editor.makeSpellCheck(); - } -} - -class TextEditor { - private SpellChecker spellChecker; - - @Inject - public TextEditor( SpellChecker spellChecker) { - this.spellChecker = spellChecker; - } - public void makeSpellCheck() { - spellChecker.checkSpelling(); - } -} - -//Binding Module -class TextEditorModule extends AbstractModule { - @Override protected void configure() { - bind(String.class).annotatedWith(Names.named("JDBC")).toInstance("jdbc:mysql://localhost:5326/emp"); - bind( SpellChecker.class ).to( SpellCheckerImpl.class ) ; - } -} - -//@ImplementedBy(SpellCheckerImpl.class) -interface SpellChecker { - public void checkSpelling(); -} - -//spell checker implementation -class SpellCheckerImpl implements SpellChecker { - private String dbUrl; - public SpellCheckerImpl(){} - - @Inject - public void setDbUrl(@Named("JDBC") String dbUrl) { - this.dbUrl = dbUrl; - } - @Override - public void checkSpelling() { - System.out.println("Inside checkSpelling." ); - System.out.println(dbUrl); - } -} From 9771150a22d58608b2c079e639ee4e3cb6f73039 Mon Sep 17 00:00:00 2001 From: Kai Nagel Date: Thu, 21 Dec 2023 10:17:16 +0100 Subject: [PATCH 4/4] change emissions --- output/.gitignore | 4 -- .../RunAverageEmissionToolOfflineExample.java | 15 ++--- .../MapBinderWithAnnotationExample.java | 31 +++++++--- .../MapBinderWithStringExample.java | 33 +++++++--- .../MultiBinderExample.java | 61 ++++++++++++++----- .../codeexamples/RunAbcSimpleExampleTest.java | 1 - 6 files changed, 93 insertions(+), 52 deletions(-) delete mode 100644 output/.gitignore diff --git a/output/.gitignore b/output/.gitignore deleted file mode 100644 index 5e7d2734..00000000 --- a/output/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore diff --git a/src/main/java/org/matsim/codeexamples/extensions/emissions/RunAverageEmissionToolOfflineExample.java b/src/main/java/org/matsim/codeexamples/extensions/emissions/RunAverageEmissionToolOfflineExample.java index a2aac1ce..d252bbe0 100644 --- a/src/main/java/org/matsim/codeexamples/extensions/emissions/RunAverageEmissionToolOfflineExample.java +++ b/src/main/java/org/matsim/codeexamples/extensions/emissions/RunAverageEmissionToolOfflineExample.java @@ -76,9 +76,6 @@ public static void main (String[] args){ emissionsConfig.setDetailedVsAverageLookupBehavior( DetailedVsAverageLookupBehavior.directlyTryAverageTable ); -// emissionsConfig.setAverageColdEmissionFactorsFile( "../sample_EFA_ColdStart_vehcat_2005average.csv" ); -// emissionsConfig.setAverageWarmEmissionFactorsFile( "../sample_EFA_HOT_vehcat_2005average.csv" ); - emissionsConfig.setAverageColdEmissionFactorsFile( "../sample_EFA_ColdStart_vehcat_2020_average_withHGVetc.csv" ); emissionsConfig.setAverageWarmEmissionFactorsFile( "../sample_41_EFA_HOT_vehcat_2020average.csv" ); @@ -110,21 +107,17 @@ public static void main (String[] args){ // we do not want to run the full Controler. In consequence, we plug together the infrastructure one needs in order to run the emissions contrib: - EventsManager eventsManager = EventsUtils.createEventsManager(); - AbstractModule module = new AbstractModule(){ @Override public void install(){ bind( Scenario.class ).toInstance( scenario ); - bind( EventsManager.class ).toInstance( eventsManager ) ; - bind( EmissionModule.class ) ; + bind( EventsManager.class ).toInstance( EventsUtils.createEventsManager() ) ; + bind( EmissionModule.class ).asEagerSingleton(); // eager singleton necessary to force instantiation! } }; com.google.inject.Injector injector = Injector.createInjector( config, module ); - - // the EmissionModule must be instantiated, otherwise it does not work: - injector.getInstance(EmissionModule.class); + EventsManager eventsManager = injector.getInstance( EventsManager.class ); // --- @@ -139,7 +132,7 @@ public void install(){ eventWriterXML.closeFile(); // also write vehicles and network and config as a service so we have all out files in one directory: - new MatsimVehicleWriter( scenario.getVehicles() ).writeFile( config.controler().getOutputDirectory() + "/output_vehicles.xml.gz" ); + VehicleUtils.writeVehicles( scenario.getVehicles() , config.controler().getOutputDirectory() + "/output_vehicles.xml.gz" ); NetworkUtils.writeNetwork( scenario.getNetwork(), config.controler().getOutputDirectory() + "/output_network.xml.gz" ); ConfigUtils.writeConfig( config, config.controler().getOutputDirectory() + "/output_config.xml" ); ConfigUtils.writeMinimalConfig( config, config.controler().getOutputDirectory() + "/output_config_reduced.xml" ); diff --git a/src/main/java/org/matsim/codeexamples/guicewithoutmatsim/MapBinderWithAnnotationExample.java b/src/main/java/org/matsim/codeexamples/guicewithoutmatsim/MapBinderWithAnnotationExample.java index cea4a6ab..8387f220 100644 --- a/src/main/java/org/matsim/codeexamples/guicewithoutmatsim/MapBinderWithAnnotationExample.java +++ b/src/main/java/org/matsim/codeexamples/guicewithoutmatsim/MapBinderWithAnnotationExample.java @@ -44,28 +44,39 @@ protected void configure(){ } log.info("") ; - Map>> map = injector.getInstance( Key.get( new TypeLiteral>>>(){} ) );; - Set> set = map.get( Names.named("abc" ) ) ; + injector.getInstance( MyRunner.class ).run(); - for( Provider provider : set ){ - provider.get() ; - } +// Map>> map = injector.getInstance( Key.get( new TypeLiteral>>>(){} ) );; +// Set> set = map.get( Names.named("abc" ) ) ; +// +// for( Provider provider : set ){ +// provider.get() ; +// } } - private interface MyInterface{ + private static class MyRunner { + @Inject private Map myInterfaceMap; + void run() { + myInterfaceMap.get(Names.named("egh")).doSomething(); + } + } + + + private interface MyInterface{ + void doSomething(); } private static class MyImpl1 implements MyInterface{ - @Inject MyImpl1() { - log.info( "ctor 1 called" ); + public void doSomething() { + log.warn("doSomething of MyImpl1"); } } private static class MyImpl2 implements MyInterface{ - @Inject MyImpl2() { - log.info( "ctor 2 called" ); + public void doSomething() { + log.warn("doSomething of MyImpl1"); } } } diff --git a/src/main/java/org/matsim/codeexamples/guicewithoutmatsim/MapBinderWithStringExample.java b/src/main/java/org/matsim/codeexamples/guicewithoutmatsim/MapBinderWithStringExample.java index 95984340..7fd68f2d 100644 --- a/src/main/java/org/matsim/codeexamples/guicewithoutmatsim/MapBinderWithStringExample.java +++ b/src/main/java/org/matsim/codeexamples/guicewithoutmatsim/MapBinderWithStringExample.java @@ -8,6 +8,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Set; public final class MapBinderWithStringExample{ private static final Logger log = LogManager.getLogger( MapBinderWithStringExample.class ) ; @@ -25,6 +26,8 @@ void run() { modules.add( new AbstractModule(){ @Override protected void configure(){ + bind( MyRunner.class ); + MapBinder mapBinder = MapBinder.newMapBinder( this.binder(), String.class, MyInterface.class ); // mapBinder.permitDuplicates() ; mapBinder.addBinding("abc" ).to( MyImpl1.class ).in( Singleton.class ); @@ -45,29 +48,39 @@ protected void configure(){ } log.info("") ; - Map> map = injector.getInstance( Key.get( new TypeLiteral>>(){} ) );; - Provider provider = map.get( "abc" );; + injector.getInstance( MyRunner.class ).run() ; -// for( Provider provider : set ){ - provider.get() ; -// } +// Map> map = injector.getInstance( Key.get( new TypeLiteral>>(){} ) );; +// Provider provider = map.get( "abc" );; +// +//// for( Provider provider : set ){ +// provider.get() ; +//// } } - private interface MyInterface{ + private static class MyRunner { + @Inject private Map myInterfaceMap; + void run() { + myInterfaceMap.get("egh").doSomething(); + } + } + + private interface MyInterface{ + void doSomething(); } @Singleton private static class MyImpl1 implements MyInterface{ - @Inject MyImpl1() { - log.info( "ctor 1 called" ); + public void doSomething() { + log.warn("doSomething in MyImpl1"); } } private static class MyImpl2 implements MyInterface{ - @Inject MyImpl2() { - log.info( "ctor 2 called" ); + public void doSomething() { + log.warn("doSomething in MyImpl2"); } } } diff --git a/src/main/java/org/matsim/codeexamples/guicewithoutmatsim/MultiBinderExample.java b/src/main/java/org/matsim/codeexamples/guicewithoutmatsim/MultiBinderExample.java index 1926a50c..0a2ed56a 100644 --- a/src/main/java/org/matsim/codeexamples/guicewithoutmatsim/MultiBinderExample.java +++ b/src/main/java/org/matsim/codeexamples/guicewithoutmatsim/MultiBinderExample.java @@ -1,10 +1,8 @@ package org.matsim.codeexamples.guicewithoutmatsim; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import java.util.*; +import com.google.inject.name.Named; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; @@ -32,15 +30,28 @@ void run() { modules.add( new AbstractModule(){ @Override protected void configure(){ + bind( MyRunner.class ); - Multibinder multiBinder = Multibinder.newSetBinder( this.binder(), MyInterface.class, Names.named( "someAnnotation" ) );; -// Multibinder multiBinder = Multibinder.newSetBinder( this.binder(), MyInterface.class );; - multiBinder.permitDuplicates() ; + Multibinder multiBinder = Multibinder.newSetBinder( this.binder(), MyInterface.class );; +// Multibinder multiBinder = Multibinder.newSetBinder( this.binder(), MyInterface.class, Names.named( "someAnnotation" ) );; multiBinder.addBinding().to( MyImpl1.class ) ; multiBinder.addBinding().to( MyImpl2.class ) ; +// multiBinder.addBinding().to( MyImpl2.class ) ; + +// multiBinder.permitDuplicates() ; + } } ) ; + + + modules.add( new AbstractModule(){ + @Override protected void configure(){ + Multibinder multibinder = Multibinder.newSetBinder( this.binder(), MyInterface.class ); + multibinder.addBinding().to( MyImpl3.class ); + } + } ); + Injector injector = Guice.createInjector( modules ); Map, Binding> bindings = injector.getAllBindings(); @@ -52,27 +63,45 @@ protected void configure(){ } log.info("") ; - Collection> set = injector.getInstance( Key.get( new TypeLiteral>>(){} , Names.named( "someAnnotation" )) ); + MyRunner myRunner = injector.getInstance( MyRunner.class ); + myRunner.run(); - for( Provider provider : set ){ - provider.get() ; - } +// Collection> set = injector.getInstance( Key.get( new TypeLiteral>>(){} , Names.named( "someAnnotation" )) ); +// for( Provider provider : set ){ +// provider.get() ; +// } } - private interface MyInterface{ + private static class MyRunner { + @Inject +// @Named("someAnnotation") + private Set myInterfaces; + void run() { + for( MyInterface myInterface : myInterfaces ){ + myInterface.doSomething(); + } + } + } + private interface MyInterface{ + void doSomething(); } private static class MyImpl1 implements MyInterface{ - @Inject MyImpl1() { - log.info( "ctor 1 called" ); + public void doSomething() { + log.warn("calling doSomething method of MyImpl1"); } } private static class MyImpl2 implements MyInterface{ - @Inject MyImpl2() { - log.info( "ctor 2 called" ); + public void doSomething() { + log.warn("calling doSomething method of MyImpl2"); + } + } + private static class MyImpl3 implements MyInterface{ + public void doSomething() { + log.warn("calling doSomething method of MyImpl3"); } } } diff --git a/src/test/java/org/matsim/codeexamples/RunAbcSimpleExampleTest.java b/src/test/java/org/matsim/codeexamples/RunAbcSimpleExampleTest.java index c0ae5074..2727f608 100644 --- a/src/test/java/org/matsim/codeexamples/RunAbcSimpleExampleTest.java +++ b/src/test/java/org/matsim/codeexamples/RunAbcSimpleExampleTest.java @@ -1,6 +1,5 @@ package org.matsim.codeexamples; -import com.jogamp.common.util.SyncedRingbuffer; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.junit.Assert;